stellar

UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

commit ef2b4628adb6a029cc81d0267d80fc9537fdb89f
parent 0f8fcd867fd7ddbae2c118b5639acc0c05e9a2af
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Mon, 7 Aug 2023 09:47:16 +0200

Mate Detection

Diffstat:
M CMakeLists.txt | + -
M src/board/board.c | + -
M src/engine/engine.c | ++++++++++++++++++++++++++++++++++++++++++++++++++ --------------------------------
M src/moves/moves.c | ++++ ----
M src/score/score.c | +++ -

5 files changed, 63 insertions(+), 42 deletions(-)


diff --git a/ CMakeLists.txt b/ CMakeLists.txt

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Stellar
VERSION 0.0.14
VERSION 0.0.15
DESCRIPTION "Chess engine written in C" HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git LANGUAGES C

diff --git a/ src/board/board.c b/ src/board/board.c

@@ -203,7 +203,7 @@ void board_print(const Board *self) { if (!file) printf(" %d ", 8 - rank);
printf("%s", (piece) ? piece_unicode(piece) : ". ");
printf("%c ", (piece) ? piece_asci(piece) : '.');
} printf("\n"); }

diff --git a/ src/engine/engine.c b/ src/engine/engine.c

@@ -19,6 +19,9 @@ #define REDUCTION_MOVE 2 #define INFINITY 50000
#define MATE_VALUE 49000
#define MATE_SCORE 48000
#define WINDOW 50 typedef struct Stats Stats;

@@ -112,9 +115,10 @@ int evaluate(const Board *board) { } int quiescence(Stats *stats, const Board *board, int alpha, int beta) {
int eval = evaluate(board);
stats->nodes++;
int eval = evaluate(board);
if (stats->ply > MAX_PLY - 1) return eval;
if (eval >= beta) return beta; if (eval > alpha) alpha = eval;

@@ -126,27 +130,32 @@ int quiescence(Stats *stats, const Board *board, int alpha, int beta) { for (int i = 0; i < move_list_size(&moves); i++) { board_copy(board, &copy);
if (move_make(move_list_move(&moves, i), &copy, 1) == 0) continue;
Move move = move_list_move(&moves, i);
if (move_make(move, &copy, 1) == 0) continue;
stats->ply++; int score = -quiescence(stats, &copy, -beta, -alpha); stats->ply--;
if (score >= beta) return beta;
if (score > alpha) alpha = score;
if (score > alpha) {
alpha = score;
if (score >= beta) return beta;
}
} return alpha; } int negamax(Stats *stats, const Board *board, int alpha, int beta, int depth) {
int ply = stats->ply;
stats->pv_length[ply] = ply;
stats->pv_length[stats->ply] = stats->ply;
stats->nodes++;
if (depth == 0) return quiescence(stats, board, alpha, beta);
if (ply > MAX_PLY - 1) return evaluate(board);
if (stats->ply > MAX_PLY - 1) return evaluate(board);
stats->nodes++;
// if (alpha < -MATE_VALUE) alpha = -MATE_VALUE;
// if (beta > MATE_VALUE - 1) beta = MATE_VALUE - 1;
// if (alpha >= beta) return alpha;
int isCheck = board_isCheck(board); if (isCheck) depth++;

@@ -158,7 +167,7 @@ int negamax(Stats *stats, const Board *board, int alpha, int beta, int depth) { board_side_switch(&copy); board_enpassant_set(&copy, no_sq);
int score = -negamax(stats, &copy, -beta, -beta + 2,
int score = -negamax(stats, &copy, -beta, -beta + 1,
depth - 1 - REDUCTION_MOVE); if (score >= beta) return beta;

@@ -170,16 +179,16 @@ int negamax(Stats *stats, const Board *board, int alpha, int beta, int depth) { if (stats->follow_pv) enable_pv_scoring(stats, &list); move_list_sort(stats, &list);
int legal_moves = 0; int searched = 0; for (int i = 0; i < move_list_size(&list); i++) { Move move = move_list_move(&list, i); board_copy(board, &copy);
if (move_make(move, &copy, 0) == 0) {
continue;
}
int makeCheck = board_isCheck(&copy);
if (move_make(move, &copy, 0) == 0) continue;
legal_moves++;
stats->ply++; int score;

@@ -188,7 +197,7 @@ int negamax(Stats *stats, const Board *board, int alpha, int beta, int depth) { } else { // Late Move Reduction if (searched >= FULL_DEPTH && depth >= REDUCTION_LIMIT &&
!isCheck && !makeCheck && !move_capture(move) &&
!isCheck && !board_isCheck(&copy) && !move_capture(move) &&
!move_promote(move)) { score = -negamax(stats, &copy, -alpha - 1, -alpha, depth - 2); } else

@@ -205,33 +214,35 @@ int negamax(Stats *stats, const Board *board, int alpha, int beta, int depth) { } stats->ply--;
legal_moves++;
searched++;
if (score >= beta) {
if (!move_capture(move)) {
stats->killer_moves[1][ply] = stats->killer_moves[0][ply];
stats->killer_moves[0][ply] = move;
}
return beta;
}
if (score > alpha) { if (!move_capture(move)) stats->history_moves[piece_index(move_piece(move))] [move_target(move)] += depth;
alpha = score;
stats->pv_table[ply][ply] = move;
for (int i = stats->ply + 1; i < stats->pv_length[ply + 1]; i++)
stats->pv_table[ply][i] = stats->pv_table[ply + 1][i];
stats->pv_length[ply] = stats->pv_length[ply + 1];
stats->pv_table[stats->ply][stats->ply] = move;
for (int i = stats->ply + 1; i < stats->pv_length[stats->ply + 1];
i++)
stats->pv_table[stats->ply][i] =
stats->pv_table[stats->ply + 1][i];
stats->pv_length[stats->ply] = stats->pv_length[stats->ply + 1];
if (score >= beta) {
if (!move_capture(move)) {
stats->killer_moves[1][stats->ply] =
stats->killer_moves[0][stats->ply];
stats->killer_moves[0][stats->ply] = move;
}
return beta;
}
} }
if (legal_moves == 0) {
if (isCheck)
return -49000 + stats->ply;
else
if (isCheck) {
return -MATE_VALUE + stats->ply;
} else
return 0; }

@@ -241,7 +252,7 @@ int negamax(Stats *stats, const Board *board, int alpha, int beta, int depth) { void move_print_UCI(Move move) { printf("%s%s", square_to_coordinates[move_source(move)], square_to_coordinates[move_target(move)]);
if (move_promote(move)) printf(" %c", piece_asci(move_piece_promote(move)));
if (move_promote(move)) printf("%c", piece_asci(move_piece_promote(move)));
} void search_position(const Board *board, int depth) {

@@ -259,8 +270,16 @@ void search_position(const Board *board, int depth) { alpha = score - 50; beta = score + 50;
printf("info score cp %d depth %d nodes %ld pv ", score, crnt,
stats.nodes);
if (score > -MATE_VALUE && score < -MATE_SCORE) {
printf("info score mate %d depth %d nodes %ld pv ",
(MATE_VALUE - score) / 2 + 1, crnt, stats.nodes);
} else if (score > MATE_SCORE && score < MATE_VALUE) {
printf("info score mate %d depth %d nodes %ld pv ",
(MATE_VALUE - score) / 2 + 1, crnt, stats.nodes);
} else {
printf("info score cp %d depth %d nodes %ld pv ", score, crnt,
stats.nodes);
}
for (int i = 0; i < stats.pv_length[0]; i++) { move_print_UCI(stats.pv_table[0][i]);

@@ -414,7 +433,7 @@ Board *Instruction_parse(Instruction *self, Board *board) { token = Instruction_token_next(self); depth = atoi(token); } else {
printf("Unknown argument %s after go\n", token);
// printf("Unknown argument %s after go\n", token);
} } search_position(board, depth);

diff --git a/ src/moves/moves.c b/ src/moves/moves.c

@@ -25,12 +25,12 @@ Move move_encode(Square src, Square tgt, Piece piece, Piece capture, } void move_print(Move move) {
printf("%5s %5s %2s %2s %2s %4d %4d %4d %4d %4d\n",
printf("%5s %5s %2c %2c %2c %4d %4d %4d %4d %4d\n",
square_to_coordinates[move_source(move)], square_to_coordinates[move_target(move)],
piece_unicode(move_piece(move)),
move_capture(move) ? piece_unicode(move_piece_capture(move)) : "X ",
move_promote(move) ? piece_unicode(move_piece_promote(move)) : "X ",
piece_asci(move_piece(move)),
move_capture(move) ? piece_asci(move_piece_capture(move)) : '.',
move_promote(move) ? piece_asci(move_piece_promote(move)) : '.',
move_double(move) ? 1 : 0, move_enpassant(move) ? 1 : 0, move_castle(move) ? 1 : 0, move_capture(move) ? 1 : 0, move_promote(move) ? 1 : 0);

diff --git a/ src/score/score.c b/ src/score/score.c

@@ -114,4 +114,6 @@ int Score_position(ePiece piece, eColor color, Square square) { return Scores[piece].position[square]; }
int Score_capture(ePiece src, ePiece tgt) { return Scores[src].capture[tgt]; }
int Score_capture(ePiece src, ePiece tgt) {
return Scores[src].capture[tgt] + 10000;
}