stellar

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

commitef2b4628adb6a029cc81d0267d80fc9537fdb89f
parent0f8fcd867fd7ddbae2c118b5639acc0c05e9a2af
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateMon, 7 Aug 2023 09:47:16 +0200

Mate Detection

Diffstat:
MCMakeLists.txt|+-
Msrc/board/board.c|+-
Msrc/engine/engine.c|++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/moves/moves.c|++++----
Msrc/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;
}