aboutsummaryrefslogtreecommitdiff
path: root/src/evaluate.cpp
diff options
context:
space:
mode:
authorAdam <adammegarules1@gmail.com>2026-07-31 12:11:58 +0200
committerAdam <adammegarules1@gmail.com>2026-07-31 12:11:58 +0200
commita550620aa894e218a738b62b9ecd042b03f7858f (patch)
tree5d6f459e9db0a6f315c6d1e1e7f54cd1feade724 /src/evaluate.cpp
parent17f245ac325cea859fb39799a9c8b088fc933808 (diff)
changes
Diffstat (limited to 'src/evaluate.cpp')
-rw-r--r--src/evaluate.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/evaluate.cpp b/src/evaluate.cpp
new file mode 100644
index 0000000..c53e64e
--- /dev/null
+++ b/src/evaluate.cpp
@@ -0,0 +1,189 @@
+#include "evaluate.hpp"
+#include "moves.hpp"
+#include <cstdlib>
+
+constexpr int PAWN_VALUE = 100;
+constexpr int KNIGHT_VALUE = 320;
+constexpr int BISHOP_VALUE = 400;
+constexpr int ROOK_VALUE = 500;
+constexpr int QUEEN_VALUE = 900;
+constexpr int MATE = 10000;
+
+static int PAWN_TABLE[64] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, // last rank promotes to a quuen
+ 50, 50, 50, 50, 50, 50, 50, 50, // comments to stop formating to ruin it
+ 10, 10, 20, 35, 35, 20, 10, 10, //
+ 5, 5, 10, 30, 30, 10, 5, 5, //
+ 0, 0, 0, 25, 25, 0, 0, 0, //
+ 5, -5, -10, 0, 0, -10, -5, 5, //
+ 5, 10, 10, -20, -20, 10, 10, 5, //
+ 0, 0, 0, 0, 0, 0, 0, 0 //
+};
+
+static int KNIGHT_TABLE[64] = {
+ -50, -40, -30, -30, -30, -30, -40, -50, //
+ -40, -20, 0, 0, 0, 0, -20, -40, //
+ -30, 0, 10, 15, 15, 10, 0, -30, //
+ -30, 5, 15, 20, 20, 15, 5, -30, //
+ -30, 0, 15, 20, 20, 15, 0, -30, //
+ -30, 5, 10, 15, 15, 10, 5, -30, //
+ -40, -20, 0, 5, 5, 0, -20, -40, //
+ -50, -40, -30, -30, -30, -30, -40, -50, //
+};
+
+static int BISHOP_TABLE[64] = {
+ -20, -10, -10, -10, -10, -10, -10, -20, //
+ -10, 5, 0, 0, 0, 0, 5, -10, //
+ -10, 10, 10, 10, 10, 10, 10, -10, //
+ -10, 0, 10, 15, 15, 10, 0, -10, //
+ -10, 5, 5, 10, 10, 5, 5, -10, //
+ -10, 0, 5, 10, 10, 5, 0, -10, //
+ -10, 0, 0, 0, 0, 0, 0, -10, //
+ -20, -10, -10, -10, -10, -10, -10, -20, //
+};
+
+static int ROOK_TABLE[64] = {
+ 0, 0, 5, 10, 10, 5, 0, 0, //
+ 5, 10, 10, 10, 10, 10, 10, 5, //
+ -5, 0, 0, 0, 0, 0, 0, -5, //
+ -5, 0, 0, 5, 5, 0, 0, -5, //
+ -5, 0, 0, 5, 5, 0, 0, -5, //
+ -5, 0, 0, 0, 0, 0, 0, -5, //
+ 5, 10, 10, 10, 10, 10, 10, 5, //
+ 0, 0, 5, 10, 10, 5, 0, 0, //
+};
+
+static int QUEEN_TABLE[64] = {
+ -20, -10, -10, -5, -5, -10, -10, -20, //
+ -10, 0, 0, 0, 0, 0, 0, -10, //
+ -10, 0, 5, 5, 5, 5, 0, -10, //
+ -5, 0, 5, 5, 5, 5, 0, -5, //
+ 0, 0, 5, 5, 5, 5, 0, -5, //
+ -10, 5, 5, 5, 5, 5, 0, -10, //
+ -10, 0, 5, 0, 0, 0, 0, -10, //
+ -20, -10, -10, -5, -5, -10, -10, -20, //
+};
+
+static int KING_TABLE_EARLY[64] = {
+ -30, -40, -40, -50, -50, -40, -40, -30, //
+ -30, -40, -40, -50, -50, -40, -40, -30, //
+ -30, -40, -40, -50, -50, -40, -40, -30, //
+ -30, -40, -40, -50, -50, -40, -40, -30, //
+ -20, -30, -30, -40, -40, -30, -30, -20, //
+ -10, -20, -20, -20, -20, -20, -20, -10, //
+ 20, 20, 0, 0, 0, 0, 20, 20, //
+ 20, 30, 10, 0, 0, 10, 30, 20, //
+};
+
+/*
+ * i cound some up with better name
+ * this function just takes square and if color is black rotate it
+ */
+static int RotateBoardForBlack(const int square, const bool color) {
+ return color ? square : (56 ^ square);
+}
+
+static int ForceKingToEdgeBonus(const Position enemyKing,
+ const Position myKing) {
+ int bonus = 0;
+
+ // Push enemy king toward edge
+ const int distToCenter =
+ std::abs(enemyKing.file - 3) + std::abs(enemyKing.rank - 3);
+
+ bonus += distToCenter * 10;
+
+ // Bring own king closer
+ const int kingDistance = std::abs(myKing.file - enemyKing.file) +
+ std::abs(myKing.rank - enemyKing.rank);
+
+ bonus += (14 - kingDistance) * 5;
+
+ return bonus;
+}
+
+static bool IsEndgame(Game *g) {
+ int queens = 0;
+ int rooks = 0;
+
+ for (const Piece &piece : g->pieces) {
+ switch (piece.type) {
+ case QUEEN:
+ queens++;
+ break;
+ case ROOK:
+ rooks++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return queens == 0 || (queens == 2 && rooks <= 1);
+}
+
+int EvaluateBoardForWhite(Game *g) {
+ switch (GetNewGameState(g)) {
+ case WHITE_WON:
+ return MATE;
+ case BLACK_WON:
+ return -MATE;
+ case DRAW:
+ return 0;
+ case TURN:
+ break;
+ }
+
+ int score = 0;
+
+ for (int i = 0; i < 64; i++) {
+ const Piece piece = g->pieces[i];
+ if (piece.type == NONEPIECE)
+ continue;
+
+ int value = 0;
+
+ switch (piece.type) {
+ case PAWN:
+ value = PAWN_VALUE;
+ value += PAWN_TABLE[RotateBoardForBlack(i, piece.color)];
+ break;
+ case KNIGHT:
+ value = KNIGHT_VALUE;
+ value += KNIGHT_TABLE[RotateBoardForBlack(i, piece.color)];
+ break;
+ case BISHOP:
+ value = BISHOP_VALUE;
+ value += BISHOP_TABLE[RotateBoardForBlack(i, piece.color)];
+ break;
+ case ROOK:
+ value = ROOK_VALUE;
+ value += ROOK_TABLE[RotateBoardForBlack(i, piece.color)];
+ break;
+ case QUEEN:
+ value = QUEEN_VALUE;
+ value += QUEEN_TABLE[RotateBoardForBlack(i, piece.color)];
+ break;
+ case KING:
+ value = KING_TABLE_EARLY[RotateBoardForBlack(i, piece.color)];
+ break;
+ default:
+ break;
+ }
+
+ if (piece.color) {
+ score += value;
+ } else {
+ score -= value;
+ }
+ }
+
+ Position whiteKing = FindKing(g, true);
+ Position blackKing = FindKing(g, false);
+
+ if (IsEndgame(g)) {
+ score += ForceKingToEdgeBonus(blackKing, whiteKing);
+ score -= ForceKingToEdgeBonus(whiteKing, blackKing);
+ }
+ return score;
+}