stellar

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 11:47:16 +0200

Mate Detection

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