stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE | |
evaluate.cpp (5068B)
1 #include "evaluate.hpp" 2 #include "bit.hpp" 3 #include "bitboard.hpp" 4 #include "piece.hpp" 5 #include "score.hpp" 6 #include "square.hpp" 7 #include "utils.hpp" 8 9 #include <array> 10 11 namespace evaluate { 12 13 typedef std::array<U64, 8> mask_fr_array; 14 inline constexpr const mask_fr_array mask_rank = []() constexpr -> mask_fr_array { 15 mask_fr_array mask_rank; 16 U64 mask = 0xFF; 17 for (uint8_t rank = 0; rank < 8; rank++) { 18 mask_rank[rank] = mask; 19 mask = bitboard::nortOne(mask); 20 } 21 return mask_rank; 22 }(); 23 24 inline constexpr const mask_fr_array mask_file = []() constexpr -> mask_fr_array { 25 mask_fr_array mask_file; 26 U64 mask = 0x0101010101010101; 27 for (uint8_t file = 0; file < 8; file++) { 28 mask_file[file] = mask; 29 mask = bitboard::eastOne(mask); 30 } 31 return mask_file; 32 }(); 33 34 inline constexpr const mask_fr_array mask_isolated = []() constexpr -> mask_fr_array { 35 mask_fr_array mask_isolated; 36 37 mask_isolated[0] = 0x0202020202020202; 38 39 U64 mask = 0x0505050505050505; 40 for (uint8_t file = 1; file < 8; file++) { 41 mask_isolated[file] = mask; 42 mask = bitboard::eastOne(mask); 43 } 44 45 return mask_isolated; 46 }(); 47 48 typedef std::array<std::array<U64, 64>, 2> mask_passed_array; 49 inline constexpr const mask_passed_array mask_passed = []() constexpr -> mask_passed_array { 50 mask_passed_array mask_passed; 51 52 U64 maskW, maskB; 53 for (uint8_t file = 0; file < 8; file++) { 54 maskW = maskB = mask_file[file] | mask_isolated[file]; 55 for (uint8_t rank = 0; rank < 8; rank++) { 56 maskW = bitboard::nortOne(maskW); 57 mask_passed[0][rank * 8 + file] = maskW; 58 59 maskB = bitboard::soutOne(maskB); 60 mask_passed[1][(7 - rank) * 8 + file] = maskB; 61 } 62 } 63 64 return mask_passed; 65 }(); 66 67 using piece::Type::BISHOP; 68 using piece::Type::KING; 69 using piece::Type::KNIGHT; 70 using piece::Type::PAWN; 71 using piece::Type::QUEEN; 72 using piece::Type::ROOK; 73 74 int16_t score_position_side(const Board &board, const color::Color side) { 75 U64 bitboard; 76 int16_t total = 0; 77 int8_t square_i; 78 79 const uint8_t side_i = to_underlying(side); 80 const U64 pawns = board.get_bitboard_piece(PAWN); 81 const U64 pawnsS = board.get_bitboard_piece(PAWN, side); 82 const U64 pawnsO = pawns & ~pawnsS; 83 84 bitboard = board.get_bitboard_piece(PAWN, side); 85 bitboard_for_each_bit(square_i, bitboard) { 86 const square::Square square = static_cast<square::Square>(square_i); 87 total += score::get(PAWN, side, square); 88 total += score::get(PAWN); 89 90 // check isolated, doubled and passed pawns 91 const uint8_t file = square::file(square), rank = square::rank(square); 92 if (!(mask_isolated[file] & pawnsS)) total -= score::pawn_isolated; 93 if (bit::count(pawnsS & mask_file[file]) > 1) total -= score::pawn_double; 94 if (!(pawnsO & mask_passed[side_i][square_i])) total += score::pawn_passed[side_i][rank]; 95 } 96 97 bitboard = board.get_bitboard_piece(KNIGHT, side); 98 bitboard_for_each_bit(square_i, bitboard) { 99 const square::Square square = static_cast<square::Square>(square_i); 100 total += score::get(KNIGHT, side, square); 101 total += score::get(KNIGHT); 102 } 103 104 bitboard = board.get_bitboard_piece(BISHOP, side); 105 bitboard_for_each_bit(square_i, bitboard) { 106 const square::Square square = static_cast<square::Square>(square_i); 107 total += score::get(BISHOP, side, square); 108 total += score::get(BISHOP); 109 } 110 111 bitboard = board.get_bitboard_piece(ROOK, side); 112 bitboard_for_each_bit(square_i, bitboard) { 113 const square::Square square = static_cast<square::Square>(square_i); 114 total += score::get(ROOK, side, square); 115 total += score::get(ROOK); 116 117 // rook on open and semi-open files 118 const uint8_t file = square::file(square); 119 if (!(pawns & mask_file[file])) total += score::score_open; 120 if (!(pawnsS & mask_file[file])) total += score::score_open_semi; 121 } 122 123 bitboard = board.get_bitboard_piece(QUEEN, side); 124 bitboard_for_each_bit(square_i, bitboard) { 125 const square::Square square = static_cast<square::Square>(square_i); 126 total += score::get(QUEEN, side, square); 127 total += score::get(QUEEN); 128 } 129 130 bitboard = board.get_bitboard_piece(KING, side); 131 bitboard_for_each_bit(square_i, bitboard) { 132 const square::Square square = static_cast<square::Square>(square_i); 133 total += score::get(KING, side, square); 134 total += score::get(KING); 135 136 // king on open and semi-open files 137 const uint8_t file = square::file(square); 138 if (!(pawns & mask_file[file])) total -= score::score_open; 139 if (!(pawnsS & mask_file[file])) total -= score::score_open_semi; 140 } 141 142 return total; 143 } 144 145 int16_t score_position(const Board &board) { 146 const int16_t score = score_position_side(board, color::WHITE) - score_position_side(board, color::BLACK); 147 return board.get_side() == color::WHITE ? score : -score; 148 } 149 150 } // namespace evaluate