2121#include " attacks.h"
2222#include " board.h"
2323#include " evalscores.h"
24+ #include < cstring>
25+ struct EvalData
26+ {
27+ int king_attackers_count[2 ] = {0 };
28+ int king_attackers_weight[2 ] = {0 };
29+ uint64_t king_ring[2 ] = {0 };
30+
31+ void init (Position const &position)
32+ {
33+ std::memset (this , 0 , sizeof (EvalData));
34+ king_ring[White] = Attacks::king (get_lsb (position.pieces .get_piece_bb <King>(White)));
35+ king_ring[Black] = Attacks::king (get_lsb (position.pieces .get_piece_bb <King>(Black)));
36+ }
37+ };
2438
25- template <PieceType pt, bool safe = false >
26- static constexpr int calculate_moblity (Position const & position, Square sq, Color us, const int * mobility_scores)
39+ template <PieceType pt, bool safe = false >
40+ static constexpr int calculate_moblity (Position const & position, EvalData &data, Square sq, Color us, const int * mobility_scores)
2741{
2842 uint64_t occupancy = position.total_occupancy ();
29- uint64_t attacks = Attacks::generate (pt, sq, occupancy);
43+ uint64_t attacks = Attacks::generate (pt, sq, occupancy);
3044
31- if constexpr (!safe)
45+ if constexpr (!safe)
46+ {
47+ if (attacks & data.king_ring [!us])
48+ {
49+ data.king_attackers_weight [us] += KingEval::attack_weight[pt] * popcount64 (attacks & data.king_ring [!us]);
50+ data.king_attackers_count [us]++;
51+ }
3252 return mobility_scores[popcount64 (attacks)];
33-
34- else
53+ }
54+ else
3555 {
3656 uint64_t enemy_pawns = position.pieces .get_piece_bb <Pawn>(!us);
37- uint64_t forward = us == White ? shift<Direction::south>(enemy_pawns) : shift<Direction::north>(enemy_pawns);
57+ uint64_t forward = us == White ? shift<Direction::south>(enemy_pawns) : shift<Direction::north>(enemy_pawns);
3858 uint64_t enemy_pawn_attacks = shift<Direction::east>(forward) | shift<Direction::west>(forward);
3959
40- return mobility_scores[popcount64 (attacks & ~enemy_pawn_attacks)];
60+ if (attacks & data.king_ring [!us])
61+ {
62+ data.king_attackers_weight [us] += KingEval::attack_weight[pt] * popcount64 (attacks & data.king_ring [!us]);
63+ data.king_attackers_count [us]++;
64+ }
65+
66+ return mobility_scores[popcount64 (attacks & ~enemy_pawn_attacks)];
4167 }
4268}
4369
4470static bool material_draw (Position const &position)
4571{
46- auto single = [](uint64_t bb) { return bb && !is_several (bb); };
72+ auto single = [](uint64_t bb)
73+ { return bb && !is_several (bb); };
4774
4875 auto &pieces = position.pieces ;
4976 auto &bitboards = position.pieces .bitboards ;
@@ -95,7 +122,7 @@ static bool pawn_is_isolated(uint64_t friend_pawns, Square sq)
95122 return !(friend_pawns & BitMask::neighbor_files[sq]);
96123}
97124
98- static bool pawn_is_stacked (uint64_t friend_pawns, Square sq)
125+ static bool pawn_is_stacked (uint64_t friend_pawns, Square sq)
99126{
100127 uint64_t sq_bb = 1ull << sq;
101128 return (shift<Direction::north>(sq_bb) & friend_pawns) | (shift<Direction::south>(sq_bb) & friend_pawns);
@@ -106,7 +133,7 @@ static Square psqt_sq(Square sq, Color color)
106133 return color == White ? flip_square (sq) : sq;
107134}
108135
109- static int evaluate_pawn (Position const &position, Square sq, Color us)
136+ static int evaluate_pawn (Position const &position, EvalData, Square sq, Color us)
110137{
111138 int score = 0 ;
112139 uint64_t enemy_pawns = position.pieces .get_piece_bb <Pawn>(!us);
@@ -120,12 +147,12 @@ static int evaluate_pawn(Position const &position, Square sq, Color us)
120147 return score;
121148}
122149
123- static int evaluate_knight (Position const &position, Square sq, Color us)
150+ static int evaluate_knight (Position const &position, EvalData &data, Square sq, Color us)
124151{
125152 int score = 0 ;
126153
127154 score += KnightEval::psqt[psqt_sq (sq, us)];
128- score += calculate_moblity<Knight, true >(position, sq, us, KnightEval::mobility);
155+ score += calculate_moblity<Knight, true >(position, data, sq, us, KnightEval::mobility);
129156
130157 return score;
131158}
@@ -145,62 +172,62 @@ static bool is_on_semiopen_file(Position const &position, Square sq)
145172 return !(file & white) || !(file & black);
146173}
147174
148- static int evaluate_rook (Position const &position, Square sq, Color us)
175+ static int evaluate_rook (Position const &position, EvalData &data, Square sq, Color us)
149176{
150177 int score = 0 ;
151178
152179 score += RookEval::psqt[psqt_sq (sq, us)];
153- score += calculate_moblity<Rook>(position, sq, us, RookEval::mobility);
154- score += is_on_open_file (position, sq) * RookEval::open_file;
180+ score += calculate_moblity<Rook>(position, data, sq, us, RookEval::mobility);
181+ score += is_on_open_file (position, sq) * RookEval::open_file;
155182 score += is_on_semiopen_file (position, sq) * RookEval::semi_open_file;
156183
157184 return score;
158185}
159186
160- static int evaluate_queen (Position const &position, Square sq, Color us)
187+ static int evaluate_queen (Position const &position, EvalData &data, Square sq, Color us)
161188{
162189 int score = 0 ;
163190
164191 score += QueenEval::psqt[psqt_sq (sq, us)];
165- score += calculate_moblity<Queen>(position, sq, us, QueenEval::mobility);
192+ score += calculate_moblity<Queen>(position, data, sq, us, QueenEval::mobility);
166193 score += is_on_open_file (position, sq) * QueenEval::open_file;
167194 score += is_on_semiopen_file (position, sq) * QueenEval::semi_open_file;
168195
169196 return score;
170197}
171198
172- static int evaluate_bishop (Position const &position, Square sq, Color us)
199+ static int evaluate_bishop (Position const &position, EvalData &data, Square sq, Color us)
173200{
174201 int score = 0 ;
175202
176203 score += BishopEval::psqt[psqt_sq (sq, us)];
177- score += calculate_moblity<Bishop>(position, sq, us, BishopEval::mobility);
204+ score += calculate_moblity<Bishop>(position, data, sq, us, BishopEval::mobility);
178205
179206 return score;
180207}
181208
182209template <typename Callable>
183- static int evaluate_piece (Position const &position, Callable F, uint64_t pieces, Color us)
210+ static int evaluate_piece (Position const &position, EvalData &data, Callable F, uint64_t pieces, Color us)
184211{
185212 int score = 0 ;
186213 while (pieces)
187214 {
188215 Square sq = pop_lsb (pieces);
189- score += F (position, sq, us);
216+ score += F (position, data, sq, us);
190217 }
191218 return score;
192219}
193220
194221template <PieceType type, typename Callable>
195- static int evaluate_piece (Position const &position, Callable F)
222+ static int evaluate_piece (Position const &position, EvalData &data, Callable F)
196223{
197224 int score = 0 ;
198225
199226 uint64_t white = position.pieces .bitboards [type] & position.pieces .colors [White];
200227 uint64_t black = position.pieces .bitboards [type] & position.pieces .colors [Black];
201228
202- score += evaluate_piece (position, F, white, Color::White);
203- score -= evaluate_piece (position, F, black, Color::Black);
229+ score += evaluate_piece (position, data, F, white, Color::White);
230+ score -= evaluate_piece (position, data, F, black, Color::Black);
204231 return score;
205232}
206233
@@ -246,10 +273,24 @@ static int get_phase(Position const &position)
246273 return phase;
247274}
248275
249- static int eval_king (Position const & position, Color us)
276+ static int eval_king (Position const & position, EvalData &data , Color us)
250277{
251278 Square sq = get_lsb (position.pieces .get_piece_bb <King>(us));
252- return KingEval::psqt[psqt_sq (sq, us)];
279+
280+ int score = KingEval::psqt[psqt_sq (sq, us)];
281+ Color enemy = !us;
282+
283+ if (data.king_attackers_count [enemy] >= 2 )
284+ {
285+ int weight = data.king_attackers_weight [enemy];
286+
287+ if (!position.pieces .get_piece_bb <Queen>(enemy))
288+ weight /= 2 ;
289+
290+ score += KingEval::safety_table[weight];
291+ }
292+
293+ return score;
253294}
254295
255296static inline int scale_score (Position const &position, int score)
@@ -267,17 +308,20 @@ int eval_position(Position const &position)
267308 if (material_draw (position))
268309 return 0 ;
269310
311+ EvalData data;
312+ data.init (position);
313+
270314 score += material_balance (position);
271- score += evaluate_piece<Pawn>(position, evaluate_pawn);
272- score += evaluate_piece<Knight>(position, evaluate_knight);
273- score += evaluate_piece<Rook>(position, evaluate_rook);
274- score += evaluate_piece<Bishop>(position, evaluate_bishop);
275- score += evaluate_piece<Queen>(position, evaluate_queen);
315+ score += evaluate_piece<Pawn>(position, data, evaluate_pawn);
316+ score += evaluate_piece<Knight>(position, data, evaluate_knight);
317+ score += evaluate_piece<Rook>(position, data, evaluate_rook);
318+ score += evaluate_piece<Bishop>(position, data, evaluate_bishop);
319+ score += evaluate_piece<Queen>(position, data, evaluate_queen);
276320
277- score += eval_king (position, White);
278- score -= eval_king (position, Black);
321+ score += eval_king (position, data, White);
322+ score -= eval_king (position, data, Black);
279323
280324 score = scale_score (position, score);
281325
282326 return position.side == White ? score : -score;
283- }
327+ }
0 commit comments