commit 37f488a52d4d9bd520d73e94fe8a8f21f6348e28
parent e611a16b9622e0b6831048b51a87cf51a2a01792
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sun, 13 Aug 2023 13:34:54 +0200
Improve scoring
Diffstat:
5 files changed, 121 insertions(+), 146 deletions(-)
diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt
@@ -1,6 +1,5 @@
add_executable(engine
engine.cpp
- score.cpp
transposition.cpp
)
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -29,16 +29,16 @@ int evaluate(const Board &board) {
uint8_t square_i;
int score = 0;
- for (piece::Type type : piece::TypeIter()) {
+ for (const piece::Type type : piece::TypeIter()) {
U64 bitboard = board.get_bitboard_piece(type);
bitboard_for_each_bit(square_i, bitboard) {
Square square = static_cast<Square>(square_i);
if (bit_get(occupancy, square_i)) {
- score += Score_value(type);
- score += Score_position(type, side, square);
+ score += piece::score(type);
+ score += piece::score(type, side, square);
} else {
- score -= Score_value(type);
- score -= Score_position(type, sideOther, square);
+ score -= piece::score(type);
+ score -= piece::score(type, sideOther, square);
}
}
}
@@ -98,7 +98,12 @@ int quiescence(Stats &stats, int alpha, int beta) {
return 20000;
}
}
- return Score_move(stats, move);
+
+ const piece::Type type = move.piece().type;
+ if (move.is_capture()) return piece::score(type, move.piece_capture().type) + 10000;
+ if (stats.killer[0][stats.ply] == move) return 9000;
+ if (stats.killer[1][stats.ply] == move) return 8000;
+ return stats.history[to_underlying(type)][to_underlying(move.target())];
};
stats.follow_pv = pv_flag;
@@ -147,11 +152,12 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
if (isCheck) depth++;
if (!pv_node && !isCheck) {
+ static constexpr const U32 score_pawn = piece::score(piece::Type::PAWN);
int staticEval = evaluate(stats.board);
// evaluation pruning
if (depth < 3 && abs(beta - 1) > -MATE_VALUE + 100) {
- int marginEval = Score_value(piece::Type::PAWN) * depth;
+ int marginEval = score_pawn * depth;
if (staticEval - marginEval >= beta) return staticEval - marginEval;
}
@@ -165,21 +171,26 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
}
// razoring
- score = staticEval + Score_value(piece::Type::PAWN);
+ score = staticEval + score_pawn;
int scoreNew = quiescence(stats, alpha, beta);
if (score < beta && depth == 1) {
return (scoreNew > score) ? scoreNew : score;
}
- score += Score_value(piece::Type::PAWN);
+ score += score_pawn;
if (score < beta && depth < 4) {
if (scoreNew < beta) return (scoreNew > score) ? scoreNew : score;
}
}
// futility pruning condition
- static const int margin[] = {0, 100, 300, 500};
+ static constexpr const int margin[] = {
+ 0,
+ piece::score(piece::Type::PAWN),
+ piece::score(piece::Type::KNIGHT),
+ piece::score(piece::Type::ROOK),
+ };
if (depth < 4 && abs(alpha) < MATE_SCORE && staticEval + margin[depth] <= alpha) futility = 1;
}
@@ -193,7 +204,11 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
return 20000;
}
}
- return Score_move(stats, move);
+ const piece::Type type = move.piece().type;
+ if (move.is_capture()) return piece::score(type, move.piece_capture().type) + 10000;
+ if (stats.killer[0][stats.ply] == move) return 9000;
+ if (stats.killer[1][stats.ply] == move) return 8000;
+ return stats.history[to_underlying(type)][to_underlying(move.target())];
};
stats.follow_pv = pv_flag;
diff --git a/src/engine/score.cpp b/src/engine/score.cpp
@@ -1,123 +0,0 @@
-#include "score.hpp"
-#include "move.hpp"
-#include "stats.hpp"
-#include "utils_cpp.hpp"
-
-// clang-format off
-struct Score_T {
- int value;
- int position[64];
- int capture[6];
-};
-
-static const struct Score_T Scores[] = {
-{
-.value = 100,
-.position = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, -10, -10, 0, 0, 0,
- 0, 0, 0, 5, 5, 0, 0, 0,
- 5, 5, 10, 20, 20, 5, 5, 5,
- 10, 10, 10, 20, 20, 10, 10, 10,
- 20, 20, 20, 30, 30, 30, 20, 20,
- 30, 30, 30, 40, 40, 30, 30, 30,
- 90, 90, 90, 90, 90, 90, 90, 90, },
-.capture = { 105, 205, 305, 405, 505, 605} },
-{
-.value = 300,
-.position = {
- -5, -10 , 0, 0, 0, 0, -10, -5,
- -5, 0, 0, 0, 0, 0, 0, -5,
- -5, 5, 20, 10, 10, 20, 5, -5,
- -5, 10, 20, 30, 30, 20, 10, -5,
- -5, 10, 20, 30, 30, 20, 10, -5,
- -5, 5, 20, 20, 20, 20, 5, -5,
- -5, 0, 0, 10, 10, 0, 0, -5,
- -5, 0, 0, 0, 0, 0, 0, -5, },
-.capture = { 104, 204, 304, 404, 504, 604} },
-{
-.value = 350,
-.position = {
- 0, 0, -10, 0, 0, -10, 0, 0,
- 0, 30, 0, 0, 0, 0, 30, 0,
- 0, 10, 0, 0, 0, 0, 10, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 0, 0, 0, 10, 10, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, },
-.capture = { 103, 203, 303, 403, 503, 603} },
-{
-.value = 500,
-.position = {
- 0, 0, 0, 20, 20, 0, 0, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 0, 0, 10, 20, 20, 10, 0, 0,
- 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, },
-.capture = { 102, 202, 302, 402, 502, 602} },
-{
-.value = 1000,
-.position = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, },
-.capture = { 101, 201, 301, 401, 501, 601} },
-{
-.value = 10000,
-.position = {
- 0, 0, 5, 0, -15, 0, 10, 0,
- 0, 5, 5, -5, -5, 0, 5, 0,
- 0, 0, 5, 10, 10, 5, 0, 0,
- 0, 5, 10, 20, 20, 10, 5, 0,
- 0, 5, 10, 20, 20, 10, 5, 0,
- 0, 5, 5, 10, 10, 5, 5, 0,
- 0, 0, 5, 5, 5, 5, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, },
-.capture = { 100, 200, 300, 400, 500, 600} },
-};
-
-const Square mirror_score[128] =
-{
- Square::a8, Square::b8, Square::c8, Square::d8, Square::e8, Square::f8, Square::g8, Square::h8,
- Square::a7, Square::b7, Square::c7, Square::d7, Square::e7, Square::f7, Square::g7, Square::h7,
- Square::a6, Square::b6, Square::c6, Square::d6, Square::e6, Square::f6, Square::g6, Square::h6,
- Square::a5, Square::b5, Square::c5, Square::d5, Square::e5, Square::f5, Square::g5, Square::h5,
- Square::a4, Square::b4, Square::c4, Square::d4, Square::e4, Square::f4, Square::g4, Square::h4,
- Square::a3, Square::b3, Square::c3, Square::d3, Square::e3, Square::f3, Square::g3, Square::h3,
- Square::a2, Square::b2, Square::c2, Square::d2, Square::e2, Square::f2, Square::g2, Square::h2,
- Square::a1, Square::b1, Square::c1, Square::d1, Square::e1, Square::f1, Square::g1, Square::h1, Square::no_sq,
-};
-// clang-format on
-
-int Score_value(piece::Type piece) { return Scores[to_underlying(piece)].value; }
-
-int Score_position(piece::Type piece, Color color, Square square) {
- if (color == Color::BLACK) square = mirror_score[to_underlying(square)];
- return Scores[to_underlying(piece)].position[to_underlying(square)];
-}
-
-U32 Score_move(const Stats &stats, Move move) {
- const int piece = to_underlying(move.piece().type);
- const int capture = to_underlying(move.piece_capture().type);
-
- if (move.is_capture()) return Scores[piece].capture[capture] + 10000;
- if (stats.killer[0][stats.ply] == move) return 9000;
- if (stats.killer[1][stats.ply] == move) return 8000;
-
- return stats.history[piece][to_underlying(move.target())];
-}
-
-void Score_move_list(const Stats &stats, MoveList &list) {
- for (auto &moveE : list) {
- moveE.score = Score_move(stats, moveE.move);
- }
-}
diff --git a/src/engine/score.hpp b/src/engine/score.hpp
@@ -1,18 +1,8 @@
#ifndef STELLAR_SCORE_H
#define STELLAR_SCORE_H
-#include "board.hpp"
-#include "movelist.hpp"
-#include "stats.hpp"
-
#define SCORE_INFINITY 50000
#define MATE_VALUE 49000
#define MATE_SCORE 48000
-U32 Score_move(const Stats &stats, Move move);
-void Score_move_list(const Stats &stats, MoveList &list);
-int Score_position(piece::Type piece, Color color, Square square);
-int Score_capture(piece::Type src, piece::Type tgt);
-int Score_value(piece::Type piece);
-
#endif
diff --git a/src/include/piece.hpp b/src/include/piece.hpp
@@ -21,7 +21,7 @@ typedef Iterator<Type, Type::PAWN, Type::KING> TypeIter;
class Piece {
public:
- constexpr U64 operator()(Square square, U64 occupancy) const { return attack(square, occupancy); }
+ constexpr U64 operator()(Square from, U64 occupancy) const { return attack(from, occupancy); }
const Type type;
const Color color;
@@ -109,6 +109,100 @@ constexpr const Piece &get_from_code(char code) {
constexpr const Piece &get_from_index(uint8_t index) { return table[index / 6][index % 6]; }
+static inline constexpr const Square mirror[65] = {
+ // clang-format off
+ Square::a8, Square::b8, Square::c8, Square::d8, Square::e8, Square::f8, Square::g8, Square::h8,
+ Square::a7, Square::b7, Square::c7, Square::d7, Square::e7, Square::f7, Square::g7, Square::h7,
+ Square::a6, Square::b6, Square::c6, Square::d6, Square::e6, Square::f6, Square::g6, Square::h6,
+ Square::a5, Square::b5, Square::c5, Square::d5, Square::e5, Square::f5, Square::g5, Square::h5,
+ Square::a4, Square::b4, Square::c4, Square::d4, Square::e4, Square::f4, Square::g4, Square::h4,
+ Square::a3, Square::b3, Square::c3, Square::d3, Square::e3, Square::f3, Square::g3, Square::h3,
+ Square::a2, Square::b2, Square::c2, Square::d2, Square::e2, Square::f2, Square::g2, Square::h2,
+ Square::a1, Square::b1, Square::c1, Square::d1, Square::e1, Square::f1, Square::g1, Square::h1, Square::no_sq,
+ // clang-format on
+};
+
+static constexpr inline const uint16_t value[6] = {100, 300, 350, 500, 1000, 10000};
+static constexpr inline const uint16_t capture[6][6] = {
+ // clang-format off
+ {105, 205, 305, 405, 505, 605},
+ {104, 204, 304, 404, 504, 604},
+ {103, 203, 303, 403, 503, 603},
+ {102, 202, 302, 402, 502, 602},
+ {101, 201, 301, 401, 501, 601},
+ {100, 200, 300, 400, 500, 600},
+ // clang-format on
+};
+static constexpr inline const int8_t position[6][64] = {
+ // clang-format off
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, -10, -10, 0, 0, 0,
+ 0, 0, 0, 5, 5, 0, 0, 0,
+ 5, 5, 10, 20, 20, 5, 5, 5,
+ 10, 10, 10, 20, 20, 10, 10, 10,
+ 20, 20, 20, 30, 30, 30, 20, 20,
+ 30, 30, 30, 40, 40, 30, 30, 30,
+ 90, 90, 90, 90, 90, 90, 90, 90
+ }, {
+ -5, -10 , 0, 0, 0, 0, -10, -5,
+ -5, 0, 0, 0, 0, 0, 0, -5,
+ -5, 5, 20, 10, 10, 20, 5, -5,
+ -5, 10, 20, 30, 30, 20, 10, -5,
+ -5, 10, 20, 30, 30, 20, 10, -5,
+ -5, 5, 20, 20, 20, 20, 5, -5,
+ -5, 0, 0, 10, 10, 0, 0, -5,
+ -5, 0, 0, 0, 0, 0, 0, -5
+ }, {
+ 0, 0, -10, 0, 0, -10, 0, 0,
+ 0, 30, 0, 0, 0, 0, 30, 0,
+ 0, 10, 0, 0, 0, 0, 10, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 0, 0, 0, 10, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }, {
+ 0, 0, 0, 20, 20, 0, 0, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 0, 0, 10, 20, 20, 10, 0, 0,
+ 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50
+ }, {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }, {
+ 0, 0, 5, 0, -15, 0, 10, 0,
+ 0, 5, 5, -5, -5, 0, 5, 0,
+ 0, 0, 5, 10, 10, 5, 0, 0,
+ 0, 5, 10, 20, 20, 10, 5, 0,
+ 0, 5, 10, 20, 20, 10, 5, 0,
+ 0, 5, 5, 10, 10, 5, 5, 0,
+ 0, 0, 5, 5, 5, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+ // clang-format on
+};
+
+constexpr uint16_t score(Type piece) { return value[to_underlying(piece)]; }
+constexpr uint16_t score(Type piece, Type captured) {
+ return capture[to_underlying(piece)][to_underlying(captured)];
+}
+
+constexpr int8_t score(Type type, Color color, Square square) {
+ if (color == Color::BLACK) square = mirror[to_underlying(square)];
+ return position[to_underlying(type)][to_underlying(square)];
+}
+
} // namespace piece
#endif