6 int material_values[NUM_PIECES][NUM_SQUARES];
8 // simple material counter for now, improve later :-)
9 void init_evaluator(void)
13 for (i = 0; i < NUM_SQUARES; ++i) {
14 material_values[PIECE_EMPTY ][i] = 0;
15 material_values[PIECE_KNIGHT][i] = 280;
16 material_values[PIECE_BISHOP][i] = 320;
17 material_values[PIECE_ROOK ][i] = 500;
18 material_values[PIECE_QUEEN ][i] = 900;
19 material_values[PIECE_KING ][i] = 20000; // more than all else combined
22 // pawns are better off near the other side, and better close to the middle
23 for (y = 0; y < 8; ++y) {
24 for (x = 0; x < 8; ++x) {
39 value += 10; // central pawns ftw
45 value += 10; // central pawns ftw
64 material_values[PIECE_PAWN][SQUARE_TO_NUM(x,y)] = value;
68 // knights hate the edges
69 for (y = 0; y < 8; ++y) {
70 for (x = 0; x < 8; ++x) {
71 if (x == 0 || x == 7 || y == 0 || y == 7)
72 material_values[PIECE_KNIGHT][SQUARE_TO_NUM(x,y)] -= 40;
73 else if (x == 1 || x == 6 || y == 1 || y == 6)
74 material_values[PIECE_KNIGHT][SQUARE_TO_NUM(x,y)] -= 15;
79 void count_pawns(const struct piece * const pieces, unsigned *pawns)
82 for (i = 0; i < 8; ++i) {
83 if (pieces[i].type == PIECE_PAWN) {
84 assert(NUM_TO_FILE(pieces[i].square) >= 0);
85 assert(NUM_TO_FILE(pieces[i].square) < 8);
86 ++pawns[NUM_TO_FILE(pieces[i].square)];
91 unsigned find_doubled_pawns(const unsigned * const pawns)
96 for (i = 0; i < 8; ++i) {
105 unsigned find_isolated_pawns(const unsigned * const pawns)
110 for (i = 0; i < 8; ++i) {
113 if (i > 0 && pawns[i - 1] > 0)
115 if (i < 8 && pawns[i + 1] > 0)
123 unsigned find_passed_pawns(const struct piece * const pieces, const struct piece * const opp_pieces, unsigned *pawns, unsigned *opp_pawns, int inverse)
128 for (i = 0; i < 8; ++i) {
131 // could be empty, or promoted (although the latter is unlikely)
132 if (pieces[i].type != PIECE_PAWN)
135 file = NUM_TO_FILE(pieces[i].square);
137 // usual heuristic: blocked by "the same pawn" on the same file
138 if (file == NUM_TO_FILE(opp_pieces[i].square) &&
139 POSSIBLY_INVERT(opp_pieces[i].square - pieces[i].square, inverse) >= 0)
142 // ok, obviously not. let's see if there's anything can indeed block it.
143 if (opp_pawns[file] > 0 || (file > 0 && opp_pawns[file - 1] > 0) || (file < 7 && opp_pawns[file + 1] > 0)) {
144 rank = NUM_TO_RANK(pieces[i].square);
145 for (j = 0; j < 8; ++j) {
148 if (opp_pieces[j].type != PIECE_PAWN)
151 // needs to be in front to block
152 if (POSSIBLY_INVERT(NUM_TO_RANK(opp_pieces[j].square) - rank, inverse) <= 0)
155 ofile = NUM_TO_FILE(opp_pieces[j].square);
156 if (file == ofile || file == ofile - 1 || file == ofile + 1)
170 // very crude, but hey
171 int king_safe(const struct piece * const pieces)
173 unsigned square = pieces[0].square;
174 unsigned full_safety = 3;
176 // c1, f1, c6, f6 are "half-safe", and are judged as the more cornered ones, only slightly
178 if (square == SQUARE_TO_NUM(2, 0) || square == SQUARE_TO_NUM(5, 0) || square == SQUARE_TO_NUM(2, 7) || square == SQUARE_TO_NUM(5, 7))
181 if (square == SQUARE_TO_NUM(0, 0) || square == SQUARE_TO_NUM(1, 0)) {
182 if (pieces[8].type != PIECE_PAWN || pieces[9].type != PIECE_PAWN || pieces[10].type != PIECE_PAWN)
185 // king on a1 or b1, just need three good pawns for full safety (ignore threats down there for now)
186 if (pieces[8].square == SQUARE_TO_NUM(0, 1) && pieces[9].square == SQUARE_TO_NUM(1, 1) && pieces[10].square == SQUARE_TO_NUM(2, 1))
188 if (pieces[8].square == SQUARE_TO_NUM(0, 2) && pieces[9].square == SQUARE_TO_NUM(1, 1) && pieces[10].square == SQUARE_TO_NUM(2, 1))
190 if (pieces[8].square == SQUARE_TO_NUM(0, 1) && pieces[9].square == SQUARE_TO_NUM(1, 2) && pieces[10].square == SQUARE_TO_NUM(2, 1))
192 if (pieces[8].square == SQUARE_TO_NUM(0, 3) && pieces[9].square == SQUARE_TO_NUM(1, 2) && pieces[10].square == SQUARE_TO_NUM(2, 1))
194 if (pieces[8].square == SQUARE_TO_NUM(0, 1) && pieces[9].square == SQUARE_TO_NUM(1, 1) && pieces[10].square == SQUARE_TO_NUM(2, 2))
196 } else if (square == SQUARE_TO_NUM(6, 0) || square == SQUARE_TO_NUM(7, 0)) {
197 if (pieces[15].type != PIECE_PAWN || pieces[14].type != PIECE_PAWN || pieces[13].type != PIECE_PAWN)
200 // king on g1 or h1, just need three good pawns for full safety (ignore threats down there for now)
201 if (pieces[15].square == SQUARE_TO_NUM(7, 1) && pieces[14].square == SQUARE_TO_NUM(6, 1) && pieces[13].square == SQUARE_TO_NUM(5, 1))
203 if (pieces[15].square == SQUARE_TO_NUM(7, 2) && pieces[14].square == SQUARE_TO_NUM(6, 1) && pieces[13].square == SQUARE_TO_NUM(5, 1))
205 if (pieces[15].square == SQUARE_TO_NUM(7, 1) && pieces[14].square == SQUARE_TO_NUM(6, 2) && pieces[13].square == SQUARE_TO_NUM(5, 1))
207 if (pieces[15].square == SQUARE_TO_NUM(7, 3) && pieces[14].square == SQUARE_TO_NUM(6, 2) && pieces[13].square == SQUARE_TO_NUM(5, 1))
209 if (pieces[15].square == SQUARE_TO_NUM(7, 1) && pieces[14].square == SQUARE_TO_NUM(6, 1) && pieces[13].square == SQUARE_TO_NUM(5, 2))
211 } else if (square == SQUARE_TO_NUM(0, 7) || square == SQUARE_TO_NUM(1, 7)) {
212 if (pieces[8].type != PIECE_PAWN || pieces[9].type != PIECE_PAWN || pieces[10].type != PIECE_PAWN)
215 // king on a8 or b8, just need three good pawns for full safety (ignore threats down there for now)
216 if (pieces[8].square == SQUARE_TO_NUM(0, 6) && pieces[9].square == SQUARE_TO_NUM(1, 6) && pieces[10].square == SQUARE_TO_NUM(2, 6))
218 if (pieces[8].square == SQUARE_TO_NUM(0, 5) && pieces[9].square == SQUARE_TO_NUM(1, 6) && pieces[10].square == SQUARE_TO_NUM(2, 6))
220 if (pieces[8].square == SQUARE_TO_NUM(0, 6) && pieces[9].square == SQUARE_TO_NUM(1, 5) && pieces[10].square == SQUARE_TO_NUM(2, 6))
222 if (pieces[8].square == SQUARE_TO_NUM(0, 3) && pieces[9].square == SQUARE_TO_NUM(1, 5) && pieces[10].square == SQUARE_TO_NUM(2, 6))
224 if (pieces[8].square == SQUARE_TO_NUM(0, 6) && pieces[9].square == SQUARE_TO_NUM(1, 6) && pieces[10].square == SQUARE_TO_NUM(2, 5))
226 } else if (square == SQUARE_TO_NUM(6, 7) || square == SQUARE_TO_NUM(7, 7)) {
227 if (pieces[15].type != PIECE_PAWN || pieces[14].type != PIECE_PAWN || pieces[13].type != PIECE_PAWN)
230 // king on g1 or h1, just need three good pawns for full safety (ignore threats down there for now)
231 if (pieces[15].square == SQUARE_TO_NUM(7, 6) && pieces[14].square == SQUARE_TO_NUM(6, 6) && pieces[13].square == SQUARE_TO_NUM(5, 6))
233 if (pieces[15].square == SQUARE_TO_NUM(7, 5) && pieces[14].square == SQUARE_TO_NUM(6, 6) && pieces[13].square == SQUARE_TO_NUM(5, 6))
235 if (pieces[15].square == SQUARE_TO_NUM(7, 6) && pieces[14].square == SQUARE_TO_NUM(6, 5) && pieces[13].square == SQUARE_TO_NUM(5, 6))
237 if (pieces[15].square == SQUARE_TO_NUM(7, 3) && pieces[14].square == SQUARE_TO_NUM(6, 5) && pieces[13].square == SQUARE_TO_NUM(5, 6))
239 if (pieces[15].square == SQUARE_TO_NUM(7, 6) && pieces[14].square == SQUARE_TO_NUM(6, 6) && pieces[13].square == SQUARE_TO_NUM(5, 5))
246 int pawn_and_king_evaluation(const struct position * const p, unsigned total_material)
248 // this is rather expensive, so we hash it
249 unsigned long long phash = hash_position_pk(p);
250 unsigned bucket = phash % PHASH_BUCKETS;
251 struct hash_pawn_entry *he = pawn_eval_table[bucket];
252 int pawn_score = 0, king_safety;
253 #ifdef PROFILE_HASHES
258 if (he->phash == phash) {
259 #ifdef PROFILE_HASHES
260 record_lookup(2, true, ++chain);
262 return he->pawn_score + ((he->king_safety * (int)total_material) >> 8);
265 #ifdef PROFILE_HASHES
269 #ifdef PROFILE_HASHES
270 record_lookup(2, false, chain);
273 // ok, need to calculate
275 unsigned white_pawns[8] = { 0 }, black_pawns[8] = { 0 };
276 count_pawns(p->white_pieces + 8, white_pawns);
277 count_pawns(p->black_pieces + 8, black_pawns);
279 // doubled pawns are bad
280 pawn_score += 20 * find_doubled_pawns(white_pawns);
281 pawn_score -= 20 * find_doubled_pawns(black_pawns);
283 // so are isolated pawns
284 pawn_score += 40 * find_isolated_pawns(white_pawns);
285 pawn_score -= 40 * find_isolated_pawns(black_pawns);
287 // but passed pawns are extraordinarily good
288 pawn_score += 80 * find_passed_pawns(p->white_pieces + 8, p->black_pieces + 8, white_pawns, black_pawns, 0);
289 pawn_score -= 80 * find_passed_pawns(p->black_pieces + 8, p->white_pieces + 8, black_pawns, white_pawns, -1);
292 king_safety = king_safe(p->white_pieces) - king_safe(p->black_pieces);
294 // insert into the hash
295 he = (struct hash_pawn_entry *)malloc(sizeof(struct hash_pawn_entry));
297 he->pawn_score = pawn_score;
298 he->king_safety = king_safety;
300 assert(bucket < PHASH_BUCKETS);
302 he->next = pawn_eval_table[bucket];
303 pawn_eval_table[bucket] = he;
305 return pawn_score + ((king_safety * (int)total_material) >> 8);
308 int evaluate(const struct position * const p)
312 unsigned white_material = 0, black_material = 0;
314 for (i = 0; i < 16; ++i) {
315 white_material += material_values[p->white_pieces[i].type][p->white_pieces[i].square];
317 for (i = 0; i < 16; ++i) {
318 black_material += material_values[p->black_pieces[i].type][NUM_SQUARES - 1 - p->black_pieces[i].square];
321 // bishop pair is good
322 if (p->white_pieces[4].type == PIECE_BISHOP && p->white_pieces[5].type == PIECE_BISHOP)
324 if (p->black_pieces[4].type == PIECE_BISHOP && p->black_pieces[5].type == PIECE_BISHOP)
327 // ability to castle is good
337 score += pawn_and_king_evaluation(p, white_material + black_material - 40000);
341 return score + white_material - black_material;