Skip to content

Commit 8d095f1

Browse files
authored
Add king-safety evaluation (#21)
Co-authored-by: lucametehau <31002793+lucametehau@users.noreply.github.com> Bench: 59118225
1 parent 41bd3ba commit 8d095f1

File tree

4 files changed

+140
-78
lines changed

4 files changed

+140
-78
lines changed

Bit-Genie/src/eval.cpp

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,56 @@
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

4470
static 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

182209
template <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

194221
template <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

255296
static 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+
}

Bit-Genie/src/eval.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#pragma once
1919
#include "misc.h"
2020

21-
2221
enum
2322
{
2423
PawnScoreMg = 114,
@@ -33,21 +32,6 @@ enum
3332
QueenScoreEg = 1175
3433
};
3534

36-
constexpr int piece_scores[13]{
37-
PawnScoreMg,
38-
KnightScoreMg,
39-
BishopScoreMg,
40-
RookScoreMg,
41-
QueenScoreMg,
42-
0,
43-
PawnScoreMg,
44-
KnightScoreMg,
45-
BishopScoreMg,
46-
RookScoreMg,
47-
QueenScoreMg,
48-
0,
49-
};
50-
5135
constexpr int get_score(Piece piece)
5236
{
5337
constexpr int pawn = S(PawnScoreMg, PawnScoreEg);
@@ -57,9 +41,9 @@ constexpr int get_score(Piece piece)
5741
constexpr int queen = S(QueenScoreMg, QueenScoreEg);
5842

5943
constexpr int scores[13]{
60-
pawn, knight, bishop, rook, queen, 0 - pawn, -knight, -bishop, -rook, -queen, 0, 0};
44+
pawn, knight, bishop, rook, queen, 0, -pawn, -knight, -bishop, -rook, -queen, 0, 0};
6145

6246
return scores[piece];
6347
}
6448

65-
int eval_position(Position const &);
49+
int eval_position(Position const &);

0 commit comments

Comments
 (0)