stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE |
evaluate.cpp (5068B)
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 int16_t score_position_side(const Board &board, const color::Color side) {
74 U64 bitboard;
75 int16_t total = 0;
76 int8_t square_i;
78 const uint8_t side_i = to_underlying(side);
79 const U64 pawns = board.get_bitboard_piece(PAWN);
80 const U64 pawnsS = board.get_bitboard_piece(PAWN, side);
81 const U64 pawnsO = pawns & ~pawnsS;
83 bitboard = board.get_bitboard_piece(PAWN, side);
84 bitboard_for_each_bit(square_i, bitboard) {
85 const square::Square square = static_cast<square::Square>(square_i);
86 total += score::get(PAWN, side, square);
87 total += score::get(PAWN);
89 // check isolated, doubled and passed pawns
90 const uint8_t file = square::file(square), rank = square::rank(square);
91 if (!(mask_isolated[file] & pawnsS)) total -= score::pawn_isolated;
92 if (bit::count(pawnsS & mask_file[file]) > 1) total -= score::pawn_double;
93 if (!(pawnsO & mask_passed[side_i][square_i])) total += score::pawn_passed[side_i][rank];
94 }
96 bitboard = board.get_bitboard_piece(KNIGHT, side);
97 bitboard_for_each_bit(square_i, bitboard) {
98 const square::Square square = static_cast<square::Square>(square_i);
99 total += score::get(KNIGHT, side, square);
100 total += score::get(KNIGHT);
101 }
103 bitboard = board.get_bitboard_piece(BISHOP, side);
104 bitboard_for_each_bit(square_i, bitboard) {
105 const square::Square square = static_cast<square::Square>(square_i);
106 total += score::get(BISHOP, side, square);
107 total += score::get(BISHOP);
108 }
110 bitboard = board.get_bitboard_piece(ROOK, side);
111 bitboard_for_each_bit(square_i, bitboard) {
112 const square::Square square = static_cast<square::Square>(square_i);
113 total += score::get(ROOK, side, square);
114 total += score::get(ROOK);
116 // rook on open and semi-open files
117 const uint8_t file = square::file(square);
118 if (!(pawns & mask_file[file])) total += score::score_open;
119 if (!(pawnsS & mask_file[file])) total += score::score_open_semi;
120 }
122 bitboard = board.get_bitboard_piece(QUEEN, side);
123 bitboard_for_each_bit(square_i, bitboard) {
124 const square::Square square = static_cast<square::Square>(square_i);
125 total += score::get(QUEEN, side, square);
126 total += score::get(QUEEN);
127 }
129 bitboard = board.get_bitboard_piece(KING, side);
130 bitboard_for_each_bit(square_i, bitboard) {
131 const square::Square square = static_cast<square::Square>(square_i);
132 total += score::get(KING, side, square);
133 total += score::get(KING);
135 // king on open and semi-open files
136 const uint8_t file = square::file(square);
137 if (!(pawns & mask_file[file])) total -= score::score_open;
138 if (!(pawnsS & mask_file[file])) total -= score::score_open_semi;
139 }
141 return total;
142 }
144 int16_t score_position(const Board &board) {
145 const int16_t score = score_position_side(board, color::WHITE) - score_position_side(board, color::BLACK);
146 return board.get_side() == color::WHITE ? score : -score;
147 }
149 } // namespace evaluate