stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE |
evaluate.cpp (6530B)
0 #include "evaluate.hpp"
1 #include "bit.hpp"
2 #include "bitboard.hpp"
3 #include "piece.hpp"
4 #include "score.hpp"
5 #include "square.hpp"
6 #include "utils.hpp"
8 #include <array>
10 namespace evaluate {
12 typedef std::array<U64, 8> mask_fr_array;
13 inline constexpr const mask_fr_array mask_rank = []() constexpr -> mask_fr_array {
14 mask_fr_array mask_rank;
15 U64 mask = 0xFF;
16 for (uint8_t rank = 0; rank < 8; rank++) {
17 mask_rank[rank] = mask;
18 mask = bitboard::nortOne(mask);
19 }
20 return mask_rank;
21 }();
23 inline constexpr const mask_fr_array mask_file = []() constexpr -> mask_fr_array {
24 mask_fr_array mask_file;
25 U64 mask = 0x0101010101010101;
26 for (uint8_t file = 0; file < 8; file++) {
27 mask_file[file] = mask;
28 mask = bitboard::eastOne(mask);
29 }
30 return mask_file;
31 }();
33 inline constexpr const mask_fr_array mask_isolated = []() constexpr -> mask_fr_array {
34 mask_fr_array mask_isolated;
36 mask_isolated[0] = 0x0202020202020202;
38 U64 mask = 0x0505050505050505;
39 for (uint8_t file = 1; file < 8; file++) {
40 mask_isolated[file] = mask;
41 mask = bitboard::eastOne(mask);
42 }
44 return mask_isolated;
45 }();
47 typedef std::array<std::array<U64, 64>, 2> mask_passed_array;
48 inline constexpr const mask_passed_array mask_passed = []() constexpr -> mask_passed_array {
49 mask_passed_array mask_passed;
51 U64 maskW, maskB;
52 for (uint8_t file = 0; file < 8; file++) {
53 maskW = maskB = mask_file[file] | mask_isolated[file];
54 for (uint8_t rank = 0; rank < 8; rank++) {
55 maskW = bitboard::nortOne(maskW);
56 mask_passed[0][rank * 8 + file] = maskW;
58 maskB = bitboard::soutOne(maskB);
59 mask_passed[1][(7 - rank) * 8 + file] = maskB;
60 }
61 }
63 return mask_passed;
64 }();
66 using piece::Type::BISHOP;
67 using piece::Type::KING;
68 using piece::Type::KNIGHT;
69 using piece::Type::PAWN;
70 using piece::Type::QUEEN;
71 using piece::Type::ROOK;
73 using score::Phase::ENDGAME;
74 using score::Phase::OPENING;
76 uint16_t score_game_phase(const Board &board) {
77 int16_t total = 0;
78 for (int type_i = KNIGHT; type_i < KING; type_i++) {
79 const piece::Type type = static_cast<piece::Type>(type_i);
80 total += bit::count(board.get_bitboard_piece(type)) * score::get(type);
81 }
82 return total;
83 }
85 int16_t score_position_side(const Board &board, const color::Color side, const uint16_t phase_score) {
86 U64 bitboard;
88 int16_t total = 0, opening = 0, endgame = 0;
89 int8_t square_i;
91 const uint8_t side_i = to_underlying(side);
92 const U64 pawns = board.get_bitboard_piece(PAWN);
93 const U64 pawnsS = board.get_bitboard_piece(PAWN, side);
94 const U64 pawnsO = pawns & ~pawnsS;
96 bitboard = board.get_bitboard_piece(PAWN, side);
97 bitboard_for_each_bit(square_i, bitboard) {
98 const square::Square square = static_cast<square::Square>(square_i);
99 opening += score::get(PAWN, side, square, OPENING) + score::get(PAWN, OPENING);
100 endgame += score::get(PAWN, side, square, ENDGAME) + score::get(PAWN, ENDGAME);
102 // check isolated, doubled and passed pawns
103 const uint8_t file = square::file(square), rank = square::rank(square);
104 if (!(mask_isolated[file] & pawnsS)) {
105 opening -= score::pawn_isolated_opening;
106 endgame -= score::pawn_isolated_endgame;
107 }
109 if (bit::count(pawnsS & mask_file[file]) > 1) {
110 opening -= score::pawn_double_opening;
111 endgame -= score::pawn_double_endgame;
112 }
114 if (!(pawnsO & mask_passed[side_i][square_i])) total += score::pawn_passed[side_i][rank];
115 }
117 bitboard = board.get_bitboard_piece(KNIGHT, side);
118 bitboard_for_each_bit(square_i, bitboard) {
119 const square::Square square = static_cast<square::Square>(square_i);
120 opening += score::get(KNIGHT, side, square, OPENING) + score::get(KNIGHT, OPENING);
121 endgame += score::get(KNIGHT, side, square, ENDGAME) + score::get(KNIGHT, ENDGAME);
122 }
124 bitboard = board.get_bitboard_piece(BISHOP, side);
125 bitboard_for_each_bit(square_i, bitboard) {
126 const square::Square square = static_cast<square::Square>(square_i);
127 opening += score::get(BISHOP, side, square, OPENING) + score::get(BISHOP, OPENING);
128 endgame += score::get(BISHOP, side, square, ENDGAME) + score::get(BISHOP, ENDGAME);
129 }
131 bitboard = board.get_bitboard_piece(ROOK, side);
132 bitboard_for_each_bit(square_i, bitboard) {
133 const square::Square square = static_cast<square::Square>(square_i);
134 opening += score::get(ROOK, side, square, OPENING) + score::get(ROOK, OPENING);
135 endgame += score::get(ROOK, side, square, ENDGAME) + score::get(ROOK, ENDGAME);
137 // rook on open and semi-open files
138 const uint8_t file = square::file(square);
139 if (!(pawns & mask_file[file])) total += score::file_open;
140 if (!(pawnsS & mask_file[file])) total += score::file_open_semi;
141 }
143 bitboard = board.get_bitboard_piece(QUEEN, side);
144 bitboard_for_each_bit(square_i, bitboard) {
145 const square::Square square = static_cast<square::Square>(square_i);
146 opening += score::get(QUEEN, side, square, OPENING) + score::get(QUEEN, OPENING);
147 endgame += score::get(QUEEN, side, square, ENDGAME) + score::get(QUEEN, ENDGAME);
148 }
150 bitboard = board.get_bitboard_piece(KING, side);
151 bitboard_for_each_bit(square_i, bitboard) {
152 const square::Square square = static_cast<square::Square>(square_i);
153 opening += score::get(KING, side, square, OPENING) + score::get(KING, OPENING);
154 endgame += score::get(KING, side, square, ENDGAME) + score::get(KING, ENDGAME);
156 // king on open and semi-open files
157 const uint8_t file = square::file(square);
158 if (!(pawns & mask_file[file])) total -= score::file_open;
159 if (!(pawnsS & mask_file[file])) total -= score::file_open_semi;
160 }
162 opening += total, endgame += total;
163 if (phase_score > score::phase_opening) return opening;
164 if (phase_score < score::phase_endgame) return endgame;
165 return score::interpolate(phase_score, opening, endgame);
166 }
168 int16_t score_position(const Board &board) {
169 const uint16_t phase_score = score_game_phase(board);
170 const int16_t score = score_position_side(board, color::WHITE, phase_score) -
171 score_position_side(board, color::BLACK, phase_score);
172 return board.get_side() == color::WHITE ? score : -score;
173 }
175 } // namespace evaluate