stellarUCI 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, ©);
if (move_make(move_list_move(&moves, i), ©, 1) == 0) continue;
Move move = move_list_move(&moves, i);
if (move_make(move, ©, 1) == 0) continue;
stats->ply++;
int score = -quiescence(stats, ©, -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(©);
board_enpassant_set(©, no_sq);
int score = -negamax(stats, ©, -beta, -beta + 2,
int score = -negamax(stats, ©, -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, ©);
if (move_make(move, ©, 0) == 0) {
continue;
}
int makeCheck = board_isCheck(©);
if (move_make(move, ©, 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(©) && !move_capture(move) &&
!move_promote(move)) {
score = -negamax(stats, ©, -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;
}