stellar

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

commit 4bb56bb0a5e36c56ed28b9b2affbef0a0f0e0c38
parent b2bec083864cef9c987174088cd2ad5169032cc3
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Fri, 28 Jul 2023 19:11:56 +0200

Fix formatting

Diffstat:
M.clang-format | 2+-
Msrc/CBoard.c | 290++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/engine.c | 1258++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/utils.c | 46++++++++++++++++++++++------------------------
4 files changed, 804 insertions(+), 792 deletions(-)

diff --git a/.clang-format b/.clang-format @@ -36,7 +36,7 @@ AllowAllParametersOfDeclarationOnNextLine: true AllowShortEnumsOnASingleLine: false AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None +AllowShortFunctionsOnASingleLine: true AllowShortLambdasOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false diff --git a/src/CBoard.c b/src/CBoard.c @@ -13,12 +13,12 @@ U64 CBoard_pieceBB_get(CBoard_T self, ePiece piece, Square target); // PIECE struct Piece_T { - ePiece piece; - eColor color; - char code; - char asci; - char *unicode; - attack_f attacks; + ePiece piece; + eColor color; + char code; + char asci; + char *unicode; + attack_f attacks; }; // clang-format off @@ -43,23 +43,22 @@ struct Piece_T Pieces[2][6] = { // clang-format on attack_f Piece_attacks(Piece_T self) { return self->attacks; } -char Piece_asci(Piece_T self) { return self->asci; } -char Piece_code(Piece_T self) { return self->code; } -char *Piece_unicode(Piece_T self) { return self->unicode; } -eColor Piece_color(Piece_T self) { return self->color; } -ePiece Piece_piece(Piece_T self) { return self->piece; } -int Piece_index(Piece_T self) { return self->color * 8 + self->piece; } +char Piece_asci(Piece_T self) { return self->asci; } +char Piece_code(Piece_T self) { return self->code; } +char *Piece_unicode(Piece_T self) { return self->unicode; } +eColor Piece_color(Piece_T self) { return self->color; } +ePiece Piece_piece(Piece_T self) { return self->piece; } +int Piece_index(Piece_T self) { return self->color * 8 + self->piece; } Piece_T Piece_fromCode(char code) { - int color = (isupper(code)) ? WHITE : BLACK; - for (int i = 0; i < 6; i++) - if (Pieces[color][i].code == code) - return &Pieces[color][i]; - return NULL; + int color = (isupper(code)) ? WHITE : BLACK; + for (int i = 0; i < 6; i++) + if (Pieces[color][i].code == code) return &Pieces[color][i]; + return NULL; } ePiece Piece_piece_fromCode(int index) { - return Pieces[WHITE][index % 8].piece; + return Pieces[WHITE][index % 8].piece; } Piece_T Piece_fromIndex(int index) { return &Pieces[index / 8][index % 8]; } @@ -67,211 +66,216 @@ Piece_T Piece_get(ePiece piece, eColor color) { return &Pieces[color][piece]; } // CBOARD struct CBoard_T { - U64 colorBB[2]; - U64 pieceBB[6]; - eColor side; - Square enpassant; - eCastle castle; + U64 colorBB[2]; + U64 pieceBB[6]; + eColor side; + Square enpassant; + eCastle castle; }; CBoard_T CBoard_new(void) { - CBoard_T p; - NEW0(p); - return p; + CBoard_T p; + NEW0(p); + return p; } void CBoard_free(CBoard_T *p) { FREE(*p); } void CBoard_copy(CBoard_T self, CBoard_T dest) { *dest = *self; } -Square CBoard_enpassant(CBoard_T self) { return self->enpassant; } +Square CBoard_enpassant(CBoard_T self) { return self->enpassant; } eCastle CBoard_castle(CBoard_T self) { return self->castle; } -eColor CBoard_side(CBoard_T self) { return self->side; } +eColor CBoard_side(CBoard_T self) { return self->side; } U64 CBoard_colorBB(CBoard_T self, eColor color) { return self->colorBB[color]; } U64 CBoard_pieceBB(CBoard_T self, ePiece piece) { return self->pieceBB[piece]; } U64 CBoard_occupancy(CBoard_T self) { - return self->colorBB[WHITE] | self->colorBB[BLACK]; + return self->colorBB[WHITE] | self->colorBB[BLACK]; } U64 CBoard_pieceBB_get(CBoard_T self, ePiece piece, Square target) { - return bit_get(self->pieceBB[piece], target); + return bit_get(self->pieceBB[piece], target); } U64 CBoard_pieceSet(CBoard_T self, Piece_T piece) { - return self->pieceBB[Piece_piece(piece)] & self->colorBB[Piece_color(piece)]; + return self->pieceBB[Piece_piece(piece)] & + self->colorBB[Piece_color(piece)]; } void CBoard_enpassant_set(CBoard_T self, Square target) { - self->enpassant = target; + self->enpassant = target; } void CBoard_colorBB_pop(CBoard_T self, eColor color, Square target) { - bit_pop(self->colorBB[color], target); + bit_pop(self->colorBB[color], target); } void CBoard_colorBB_set(CBoard_T self, eColor color, Square target) { - bit_set(self->colorBB[color], target); + bit_set(self->colorBB[color], target); } U64 CBoard_colorBB_get(CBoard_T self, eColor color, Square target) { - return bit_get(self->colorBB[color], target); + return bit_get(self->colorBB[color], target); } int CBoard_piece_get(CBoard_T self, Square square) { - for (int i = 0; i < 6; i++) - if (bit_get(self->pieceBB[i], square)) - return i; - return -1; + for (int i = 0; i < 6; i++) + if (bit_get(self->pieceBB[i], square)) return i; + return -1; } void CBoard_piece_pop(CBoard_T self, Piece_T Piece, Square square) { - bit_pop(self->pieceBB[Piece->piece], square); - bit_pop(self->colorBB[Piece->color], square); + bit_pop(self->pieceBB[Piece->piece], square); + bit_pop(self->colorBB[Piece->color], square); } void CBoard_piece_set(CBoard_T self, Piece_T Piece, Square square) { - bit_set(self->pieceBB[Piece->piece], square); - bit_set(self->colorBB[Piece->color], square); + bit_set(self->pieceBB[Piece->piece], square); + bit_set(self->colorBB[Piece->color], square); } void CBoard_piece_move(CBoard_T self, Piece_T Piece, Square source, Square target) { - CBoard_piece_pop(self, Piece, source); - CBoard_piece_set(self, Piece, target); + CBoard_piece_pop(self, Piece, source); + CBoard_piece_set(self, Piece, target); } U64 CBoard_piece_attacks(CBoard_T self, Piece_T Piece, Square src) { - return Piece_attacks(Piece)(src, CBoard_occupancy(self)); + return Piece_attacks(Piece)(src, CBoard_occupancy(self)); } void CBoard_piece_capture(CBoard_T self, Piece_T Piece, Piece_T Taken, Square source, Square target) { - CBoard_piece_pop(self, Piece, source); - if (Taken) - CBoard_piece_pop(self, Taken, target); - CBoard_piece_set(self, Piece, target); + CBoard_piece_pop(self, Piece, source); + if (Taken) CBoard_piece_pop(self, Taken, target); + CBoard_piece_set(self, Piece, target); } void CBoard_castle_pop(CBoard_T self, eCastle castle) { - bit_pop(self->castle, bit_lsb_index(castle)); + bit_pop(self->castle, bit_lsb_index(castle)); } void CBoard_castle_and(CBoard_T self, int exp) { self->castle &= exp; } void CBoard_side_switch(CBoard_T self) { self->side = !self->side; } int CBoard_isCheck(CBoard_T self) { - U64 king = self->pieceBB[KING] & self->colorBB[self->side]; - return CBoard_square_isAttack(self, bit_lsb_index(king), !self->side); + U64 king = self->pieceBB[KING] & self->colorBB[self->side]; + return CBoard_square_isAttack(self, bit_lsb_index(king), !self->side); } int CBoard_square_isOccupied(CBoard_T self, Square square) { - return bit_get(CBoard_occupancy(self), square); + return bit_get(CBoard_occupancy(self), square); } int CBoard_square_isAttack(CBoard_T self, Square square, eColor side) { - U64 occupancy = self->colorBB[WHITE] | self->colorBB[BLACK]; + U64 occupancy = self->colorBB[WHITE] | self->colorBB[BLACK]; - for (int i = 0; i < 6; i++) { - if (Pieces[!side][i].attacks(square, occupancy) & self->pieceBB[i] & - self->colorBB[side]) - return 1; - } + for (int i = 0; i < 6; i++) { + if (Pieces[!side][i].attacks(square, occupancy) & self->pieceBB[i] & + self->colorBB[side]) + return 1; + } - return 0; + return 0; } Piece_T CBoard_square_piece(CBoard_T self, Square square, eColor color) { - for (ePiece i = 0; i < 6; i++) - if (CBoard_pieceBB_get(self, i, square)) - return Piece_get(i, color); - return NULL; + for (ePiece i = 0; i < 6; i++) + if (CBoard_pieceBB_get(self, i, square)) return Piece_get(i, color); + return NULL; } void CBoard_print(CBoard_T self) { - for (int rank = 0; rank < 8; rank++) { - for (int file = 0; file < 8; file++) { - Square square = (7 - rank) * 8 + file; - Piece_T piece = NULL; - - int color = -1; - if (bit_get(self->colorBB[WHITE], square)) - color = WHITE; - else if (bit_get(self->colorBB[BLACK], square)) - color = BLACK; - - if (color != -1) { - for (int piece_index = 0; piece_index < 6; piece_index++) { - if (bit_get(self->pieceBB[piece_index], square)) { - piece = &Pieces[color][piece_index]; - break; - } + for (int rank = 0; rank < 8; rank++) { + for (int file = 0; file < 8; file++) { + Square square = (7 - rank) * 8 + file; + Piece_T piece = NULL; + + int color = -1; + if (bit_get(self->colorBB[WHITE], square)) + color = WHITE; + else if (bit_get(self->colorBB[BLACK], square)) + color = BLACK; + + if (color != -1) { + for (int piece_index = 0; piece_index < 6; piece_index++) { + if (bit_get(self->pieceBB[piece_index], square)) { + piece = &Pieces[color][piece_index]; + break; + } + } + } + + if (!file) printf(" %d ", 8 - rank); + + printf("%s", (piece) ? Piece_unicode(piece) : ". "); } - } - - if (!file) - printf(" %d ", 8 - rank); - - printf("%s", (piece) ? Piece_unicode(piece) : ". "); + printf("\n"); } + printf(" A B C D E F G H\n"); + printf(" Side: %s\n", (self->side == WHITE) ? "white" : "black"); + printf("Enpassant: %s\n", square_to_coordinates[self->enpassant]); + printf(" Castling: %c%c%c%c\n", (self->castle & WK) ? 'K' : '-', + (self->castle & WQ) ? 'Q' : '-', (self->castle & BK) ? 'k' : '-', + (self->castle & BQ) ? 'q' : '-'); printf("\n"); - } - printf(" A B C D E F G H\n"); - printf(" Side: %s\n", (self->side == WHITE) ? "white" : "black"); - printf("Enpassant: %s\n", square_to_coordinates[self->enpassant]); - printf(" Castling: %c%c%c%c\n", (self->castle & WK) ? 'K' : '-', - (self->castle & WQ) ? 'Q' : '-', (self->castle & BK) ? 'k' : '-', - (self->castle & BQ) ? 'q' : '-'); - printf("\n"); } CBoard_T CBoard_fromFEN(CBoard_T board, char *fen) { - if (!board) - NEW(board); - - memset(board, 0, sizeof(*board)); - - board->side = -1; - board->enpassant = no_sq; - board->castle = 0; + if (!board) NEW(board); + + memset(board, 0, sizeof(*board)); + + board->side = -1; + board->enpassant = no_sq; + board->castle = 0; + + int file = 0, rank = 7; + for (Piece_T piece; *fen != ' '; fen++) { + Square square = rank * 8 + file; + if (isalpha(*fen)) { + if (!(piece = Piece_fromCode(*fen))) assert(0); + bit_set(board->colorBB[piece->color], square); + bit_set(board->pieceBB[piece->piece], square); + file++; + } else if (isdigit(*fen)) { + file += *fen - '0'; + } else if (*fen == '/') { + file = 0; + rank--; + } else + assert(0); + } - int file = 0, rank = 7; - for (Piece_T piece; *fen != ' '; fen++) { - Square square = rank * 8 + file; - if (isalpha(*fen)) { - if (!(piece = Piece_fromCode(*fen))) + fen++; + if (*fen == 'w') + board->side = WHITE; + else if (*fen == 'b') + board->side = BLACK; + else assert(0); - bit_set(board->colorBB[piece->color], square); - bit_set(board->pieceBB[piece->piece], square); - file++; - } else if (isdigit(*fen)) { - file += *fen - '0'; - } else if (*fen == '/') { - file = 0; - rank--; - } else - assert(0); - } - - fen++; - if (*fen == 'w') - board->side = WHITE; - else if (*fen == 'b') - board->side = BLACK; - else - assert(0); - - for (fen += 2; *fen != ' '; fen++) { - switch (*fen) { - case 'K': board->castle |= WK; break; - case 'Q': board->castle |= WQ; break; - case 'k': board->castle |= BK; break; - case 'q': board->castle |= BQ; break; - case '-': break; - default: assert(0); + + for (fen += 2; *fen != ' '; fen++) { + switch (*fen) { + case 'K': + board->castle |= WK; + break; + case 'Q': + board->castle |= WQ; + break; + case 'k': + board->castle |= BK; + break; + case 'q': + board->castle |= BQ; + break; + case '-': + break; + default: + assert(0); + } } - } - fen++; - if (*fen != '-') { - board->enpassant = coordinates_to_square(fen); - } + fen++; + if (*fen != '-') { + board->enpassant = coordinates_to_square(fen); + } - return board; + return board; } diff --git a/src/engine.c b/src/engine.c @@ -15,47 +15,50 @@ // FEN debug positions #define empty_board "8/8/8/8/8/8/8/8 w - - " #define start_position \ - "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 " + "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 " #define tricky_position \ - "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 " + "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 " #define killer_position \ - "rnbqkb1r/pp1p1pPp/8/2p1pP2/1P1P4/3P3P/P1P1P3/RNBQKBNR w KQkq e6 0 1" + "rnbqkb1r/pp1p1pPp/8/2p1pP2/1P1P4/3P3P/P1P1P3/RNBQKBNR w KQkq e6 0 1" #define cmk_position \ - "r2q1rk1/ppp2ppp/2n1bn2/2b1p3/3pP3/3P1NPP/PPP1NPB1/R1BQ1RK1 b - - 0 9 " + "r2q1rk1/ppp2ppp/2n1bn2/2b1p3/3pP3/3P1NPP/PPP1NPB1/R1BQ1RK1 b - - 0 9 " typedef U32 Move; Move Move_encode(Square src, Square tgt, Piece_T Piece, Piece_T Capture, Piece_T Promote, int dbl, int enpassant, int castle) { - Move move = C32(0); - move |= (src) | (tgt << 6) | (dbl << 27) | (enpassant << 28) | (castle << 29); - move |= (Piece_index(Piece) << 12); - if (Capture != NULL) { - move |= (Piece_index(Capture) << 17); - move |= (1 << 30); - } - - if (Promote != NULL) { - move |= (Piece_index(Promote) << 22); - move |= (1 << 31); - } - - return move; + Move move = C32(0); + move |= + (src) | (tgt << 6) | (dbl << 27) | (enpassant << 28) | (castle << 29); + move |= (Piece_index(Piece) << 12); + if (Capture != NULL) { + move |= (Piece_index(Capture) << 17); + move |= (1 << 30); + } + + if (Promote != NULL) { + move |= (Piece_index(Promote) << 22); + move |= (1 << 31); + } + + return move; } -#define Move_source(move) (((move)&C32(0x0000003f))) -#define Move_target(move) (((move)&C32(0x00000fc0)) >> 6) -#define Move_double(move) (((move)&C32(0x08000000)) >> 27) +#define Move_source(move) (((move)&C32(0x0000003f))) +#define Move_target(move) (((move)&C32(0x00000fc0)) >> 6) +#define Move_double(move) (((move)&C32(0x08000000)) >> 27) #define Move_enpassant(move) (((move)&C32(0x10000000)) >> 28) -#define Move_castle(move) (((move)&C32(0x20000000)) >> 29) -#define Move_capture(move) (((move)&C32(0x40000000)) >> 30) -#define Move_promote(move) (((move)&C32(0x80000000)) >> 31) +#define Move_castle(move) (((move)&C32(0x20000000)) >> 29) +#define Move_capture(move) (((move)&C32(0x40000000)) >> 30) +#define Move_promote(move) (((move)&C32(0x80000000)) >> 31) #define Move_piece(move) (Piece_fromIndex(((move)&C32(0x0001F000)) >> 12)) #define Move_piece_capture(move) \ - (assert(Move_capture(move)), Piece_fromIndex(((move)&C32(0x003E0000)) >> 17)) + (assert(Move_capture(move)), \ + Piece_fromIndex(((move)&C32(0x003E0000)) >> 17)) #define Move_piece_promote(move) \ - (assert(Move_promote(move)), Piece_fromIndex(((move)&C32(0x07C00000)) >> 22)) + (assert(Move_promote(move)), \ + Piece_fromIndex(((move)&C32(0x07C00000)) >> 22)) // clang-format off const int castling_rights[64] = { @@ -178,9 +181,8 @@ const int mirror_score[128] = int Score_value(ePiece piece) { return Scores[piece].value; } int Score_position(ePiece piece, eColor color, Square square) { - if (color == BLACK) - square = mirror_score[square]; - return Scores[piece].position[square]; + if (color == BLACK) square = mirror_score[square]; + return Scores[piece].position[square]; } int Score_capture(ePiece src, ePiece tgt) { return Scores[src].capture[tgt]; } @@ -189,780 +191,788 @@ int Score_capture(ePiece src, ePiece tgt) { return Scores[src].capture[tgt]; } typedef struct Stats_T *Stats_T; struct Stats_T { - long nodes; - int ply; - int pv_length[MAX_PLY]; - Move pv_table[MAX_PLY][MAX_PLY]; - Move killer_moves[2][MAX_PLY]; - Move history_moves[16][64]; + long nodes; + int ply; + int pv_length[MAX_PLY]; + Move pv_table[MAX_PLY][MAX_PLY]; + Move killer_moves[2][MAX_PLY]; + Move history_moves[16][64]; }; Stats_T Stats_new(void) { - Stats_T p; - NEW0(p); - return p; + Stats_T p; + NEW0(p); + return p; } void Stats_free(Stats_T *p) { FREE(*p); } int Move_score(Stats_T stats, Move move) { - if (Move_capture(move)) { - return Score_capture(Piece_piece(Move_piece(move)), - Piece_piece(Move_piece_capture(move))); - } else { - if (stats->killer_moves[0][stats->ply] == move) - return 9000; - else if (stats->killer_moves[1][stats->ply] == move) - return 8000; - else - return stats - ->history_moves[Piece_index(Move_piece(move))][Move_target(move)]; - } - - return 0; + if (Move_capture(move)) { + return Score_capture(Piece_piece(Move_piece(move)), + Piece_piece(Move_piece_capture(move))); + } else { + if (stats->killer_moves[0][stats->ply] == move) + return 9000; + else if (stats->killer_moves[1][stats->ply] == move) + return 8000; + else + return stats->history_moves[Piece_index(Move_piece(move))] + [Move_target(move)]; + } + + return 0; } void Move_print(Move move) { - printf("%5s %5s %2s %2s %2s %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 ", - 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); + printf("%5s %5s %2s %2s %2s %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 ", + 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); } typedef struct MoveList_T *MoveList_T; struct MoveList_T { - Move moves[256]; - int count; + Move moves[256]; + int count; }; MoveList_T MoveList_new(void) { - MoveList_T p; - NEW0(p); - return p; + MoveList_T p; + NEW0(p); + return p; } void MoveList_free(MoveList_T *p) { FREE(*p); } Move MoveList_move(MoveList_T self, int index) { return self->moves[index]; } -int MoveList_size(MoveList_T self) { return self->count; } +int MoveList_size(MoveList_T self) { return self->count; } void MoveList_reset(MoveList_T self) { self->count = 0; } void MoveList_add(MoveList_T self, Move move) { - self->moves[self->count++] = move; + self->moves[self->count++] = move; } void MoveList_print(MoveList_T self) { - printf(" From To Pi Cap Prmt Dbl Enp Cst C P\n"); - for (int i = 0; i < self->count; i++) - Move_print(self->moves[i]); - printf("Total: %d\n", self->count); + printf(" From To Pi Cap Prmt Dbl Enp Cst C P\n"); + for (int i = 0; i < self->count; i++) + Move_print(self->moves[i]); + printf("Total: %d\n", self->count); } void MoveList_sort(Stats_T stats, MoveList_T list) { - int score[list->count]; - for (int i = 0; i < list->count; i++) - score[i] = Move_score(stats, list->moves[i]); - - for (int i = 0; i < list->count; i++) - for (int j = i + 1; j < list->count; j++) - if (score[i] < score[j]) { - Move t = list->moves[i]; - list->moves[i] = list->moves[j]; - list->moves[j] = t; - - int s = score[i]; - score[i] = score[j]; - score[j] = s; - } + int score[list->count]; + for (int i = 0; i < list->count; i++) + score[i] = Move_score(stats, list->moves[i]); + + for (int i = 0; i < list->count; i++) + for (int j = i + 1; j < list->count; j++) + if (score[i] < score[j]) { + Move t = list->moves[i]; + list->moves[i] = list->moves[j]; + list->moves[j] = t; + + int s = score[i]; + score[i] = score[j]; + score[j] = s; + } } #define pawn_canPromote(color, source) \ - ((color == WHITE && source >= a7 && source <= h7) || \ - (color == BLACK && source >= a2 && source <= h2)) + ((color == WHITE && source >= a7 && source <= h7) || \ + (color == BLACK && source >= a2 && source <= h2)) #define pawn_onStart(color, source) \ - ((color == BLACK && source >= a7 && source <= h7) || \ - (color == WHITE && source >= a2 && source <= h2)) + ((color == BLACK && source >= a7 && source <= h7) || \ + (color == WHITE && source >= a2 && source <= h2)) #define pawn_promote(source, target, Piece, Capture) \ - for (int i = 1; i < 5; i++) { \ - move = Move_encode(source, target, Piece, Capture, Piece_get(i, color), 0, \ - 0, 0); \ - MoveList_add(moves, move); \ - } + for (int i = 1; i < 5; i++) { \ + move = Move_encode(source, target, Piece, Capture, \ + Piece_get(i, color), 0, 0, 0); \ + MoveList_add(moves, move); \ + } MoveList_T MoveList_generate(MoveList_T moves, CBoard_T board) { - Move move; - Square src, tgt; - eColor color = CBoard_side(board); - - if (!moves) - moves = MoveList_new(); - - { // pawn moves - Piece_T Piece = Piece_get(PAWN, color); - U64 bitboard = CBoard_pieceSet(board, Piece); - bitboard_for_each_bit(src, bitboard) { - { // quiet - int add = (color == WHITE) ? +8 : -8; - tgt = src + add; - if (tgt > a1 && tgt < h8 && !CBoard_square_isOccupied(board, tgt)) { - if (pawn_canPromote(color, src)) { - pawn_promote(src, tgt, Piece, 0); - } else { - MoveList_add(moves, Move_encode(src, tgt, Piece, 0, 0, 0, 0, 0)); - - // two ahead - if (pawn_onStart(color, src) && - !CBoard_square_isOccupied(board, tgt += add)) - MoveList_add(moves, Move_encode(src, tgt, Piece, 0, 0, 1, 0, 0)); - } + Move move; + Square src, tgt; + eColor color = CBoard_side(board); + + if (!moves) moves = MoveList_new(); + + { // pawn moves + Piece_T Piece = Piece_get(PAWN, color); + U64 bitboard = CBoard_pieceSet(board, Piece); + bitboard_for_each_bit(src, bitboard) { + { // quiet + int add = (color == WHITE) ? +8 : -8; + tgt = src + add; + if (tgt > a1 && tgt < h8 && + !CBoard_square_isOccupied(board, tgt)) { + if (pawn_canPromote(color, src)) { + pawn_promote(src, tgt, Piece, 0); + } else { + MoveList_add( + moves, Move_encode(src, tgt, Piece, 0, 0, 0, 0, 0)); + + // two ahead + if (pawn_onStart(color, src) && + !CBoard_square_isOccupied(board, tgt += add)) + MoveList_add(moves, Move_encode(src, tgt, Piece, 0, + 0, 1, 0, 0)); + } + } + } + { // capture + U64 attack = CBoard_piece_attacks(board, Piece, src) & + CBoard_colorBB(board, !color); + bitboard_for_each_bit(tgt, attack) { + if (pawn_canPromote(color, src)) { + pawn_promote(src, tgt, Piece, + CBoard_square_piece(board, tgt, !color)); + } else { + MoveList_add(moves, Move_encode(src, tgt, Piece, + CBoard_square_piece( + board, tgt, !color), + 0, 0, 0, 0)); + } + } + } + + { // en passant + if (CBoard_enpassant(board) != no_sq && + CBoard_piece_attacks(board, Piece, src) & + (C64(1) << CBoard_enpassant(board))) + MoveList_add( + moves, + Move_encode(src, CBoard_enpassant(board), Piece, + CBoard_square_piece(board, tgt, !color), 0, + 0, 1, 0)); + } } - } - { // capture - U64 attack = CBoard_piece_attacks(board, Piece, src) & - CBoard_colorBB(board, !color); - bitboard_for_each_bit(tgt, attack) { - if (pawn_canPromote(color, src)) { - pawn_promote(src, tgt, Piece, - CBoard_square_piece(board, tgt, !color)); - } else { - MoveList_add(moves, - Move_encode(src, tgt, Piece, - CBoard_square_piece(board, tgt, !color), 0, - 0, 0, 0)); - } - } - } - - { // en passant - if (CBoard_enpassant(board) != no_sq && - CBoard_piece_attacks(board, Piece, src) & - (C64(1) << CBoard_enpassant(board))) - MoveList_add(moves, - Move_encode(src, CBoard_enpassant(board), Piece, - CBoard_square_piece(board, tgt, !color), 0, - 0, 1, 0)); - } } - } - - // All piece move - for (int piece = 1; piece < 6; piece++) { - Piece_T Piece = Piece_get(piece, color); - U64 bitboard = CBoard_pieceSet(board, Piece); - bitboard_for_each_bit(src, bitboard) { - U64 attack = CBoard_piece_attacks(board, Piece, src) & - ~CBoard_colorBB(board, color); - bitboard_for_each_bit(tgt, attack) { - /* int take = bit_get(CBoard_colorBB(board, !color), tgt); */ - MoveList_add(moves, Move_encode(src, tgt, Piece, - CBoard_square_piece(board, tgt, !color), - 0, 0, 0, 0)); - } + + // All piece move + for (int piece = 1; piece < 6; piece++) { + Piece_T Piece = Piece_get(piece, color); + U64 bitboard = CBoard_pieceSet(board, Piece); + bitboard_for_each_bit(src, bitboard) { + U64 attack = CBoard_piece_attacks(board, Piece, src) & + ~CBoard_colorBB(board, color); + bitboard_for_each_bit(tgt, attack) { + /* int take = bit_get(CBoard_colorBB(board, !color), tgt); */ + MoveList_add( + moves, Move_encode(src, tgt, Piece, + CBoard_square_piece(board, tgt, !color), + 0, 0, 0, 0)); + } + } } - } - - // Castling - { - if (color == WHITE) { - Piece_T Piece = Piece_get(KING, WHITE); - if (CBoard_castle(board) & WK) { - if (!CBoard_square_isOccupied(board, f1) && - !CBoard_square_isOccupied(board, g1) && - !CBoard_square_isAttack(board, e1, BLACK) && - !CBoard_square_isAttack(board, f1, BLACK)) - MoveList_add(moves, Move_encode(e1, g1, Piece, 0, 0, 0, 0, 1)); - } - if (CBoard_castle(board) & WQ) { - if (!CBoard_square_isOccupied(board, d1) && - !CBoard_square_isOccupied(board, c1) && - !CBoard_square_isOccupied(board, b1) && - !CBoard_square_isAttack(board, e1, BLACK) && - !CBoard_square_isAttack(board, d1, BLACK)) - MoveList_add(moves, Move_encode(e1, c1, Piece, 0, 0, 0, 0, 1)); - } - } else { - Piece_T Piece = Piece_get(KING, BLACK); - if (CBoard_castle(board) & BK) { - if (!CBoard_square_isOccupied(board, f8) && - !CBoard_square_isOccupied(board, g8) && - !CBoard_square_isAttack(board, e8, WHITE) && - !CBoard_square_isAttack(board, f8, WHITE)) - MoveList_add(moves, Move_encode(e8, g8, Piece, 0, 0, 0, 0, 1)); - } - if (CBoard_castle(board) & BQ) { - if (!CBoard_square_isOccupied(board, d8) && - !CBoard_square_isOccupied(board, c8) && - !CBoard_square_isOccupied(board, b8) && - !CBoard_square_isAttack(board, e8, WHITE) && - !CBoard_square_isAttack(board, d8, WHITE)) - MoveList_add(moves, Move_encode(e8, c8, Piece, 0, 0, 0, 0, 1)); - } + + // Castling + { + if (color == WHITE) { + Piece_T Piece = Piece_get(KING, WHITE); + if (CBoard_castle(board) & WK) { + if (!CBoard_square_isOccupied(board, f1) && + !CBoard_square_isOccupied(board, g1) && + !CBoard_square_isAttack(board, e1, BLACK) && + !CBoard_square_isAttack(board, f1, BLACK)) + MoveList_add(moves, + Move_encode(e1, g1, Piece, 0, 0, 0, 0, 1)); + } + if (CBoard_castle(board) & WQ) { + if (!CBoard_square_isOccupied(board, d1) && + !CBoard_square_isOccupied(board, c1) && + !CBoard_square_isOccupied(board, b1) && + !CBoard_square_isAttack(board, e1, BLACK) && + !CBoard_square_isAttack(board, d1, BLACK)) + MoveList_add(moves, + Move_encode(e1, c1, Piece, 0, 0, 0, 0, 1)); + } + } else { + Piece_T Piece = Piece_get(KING, BLACK); + if (CBoard_castle(board) & BK) { + if (!CBoard_square_isOccupied(board, f8) && + !CBoard_square_isOccupied(board, g8) && + !CBoard_square_isAttack(board, e8, WHITE) && + !CBoard_square_isAttack(board, f8, WHITE)) + MoveList_add(moves, + Move_encode(e8, g8, Piece, 0, 0, 0, 0, 1)); + } + if (CBoard_castle(board) & BQ) { + if (!CBoard_square_isOccupied(board, d8) && + !CBoard_square_isOccupied(board, c8) && + !CBoard_square_isOccupied(board, b8) && + !CBoard_square_isAttack(board, e8, WHITE) && + !CBoard_square_isAttack(board, d8, WHITE)) + MoveList_add(moves, + Move_encode(e8, c8, Piece, 0, 0, 0, 0, 1)); + } + } } - } - return moves; + return moves; } int Move_make(Move move, CBoard_T board, int flag) { - if (flag == 0) { - - Square source = Move_source(move); - Square target = Move_target(move); - Piece_T Piece = Move_piece(move); - eColor color = CBoard_side(board); - - if (!Move_capture(move)) - CBoard_piece_move(board, Piece, source, target); - else - CBoard_piece_capture(board, Piece, Move_piece_capture(move), source, - target); - - if (Move_promote(move)) { - CBoard_piece_pop(board, Piece, target); - CBoard_piece_set(board, Move_piece_promote(move), target); - } + if (flag == 0) { + + Square source = Move_source(move); + Square target = Move_target(move); + Piece_T Piece = Move_piece(move); + eColor color = CBoard_side(board); + + if (!Move_capture(move)) + CBoard_piece_move(board, Piece, source, target); + else + CBoard_piece_capture(board, Piece, Move_piece_capture(move), source, + target); + + if (Move_promote(move)) { + CBoard_piece_pop(board, Piece, target); + CBoard_piece_set(board, Move_piece_promote(move), target); + } - { - int ntarget = target + (color == WHITE ? -8 : +8); - if (Move_enpassant(move)) - CBoard_piece_pop(board, Piece_get(PAWN, !color), ntarget); + { + int ntarget = target + (color == WHITE ? -8 : +8); + if (Move_enpassant(move)) + CBoard_piece_pop(board, Piece_get(PAWN, !color), ntarget); - CBoard_enpassant_set(board, Move_double(move) ? ntarget : no_sq); - } + CBoard_enpassant_set(board, Move_double(move) ? ntarget : no_sq); + } - if (Move_castle(move)) { - Piece_T Rook = Piece_get(ROOK, CBoard_side(board)); - switch (target) { - case g1: CBoard_piece_move(board, Rook, h1, f1); break; - case c1: CBoard_piece_move(board, Rook, a1, d1); break; - case g8: CBoard_piece_move(board, Rook, h8, f8); break; - case c8: CBoard_piece_move(board, Rook, a8, d8); break; - default: break; - } - } + if (Move_castle(move)) { + Piece_T Rook = Piece_get(ROOK, CBoard_side(board)); + switch (target) { + case g1: + CBoard_piece_move(board, Rook, h1, f1); + break; + case c1: + CBoard_piece_move(board, Rook, a1, d1); + break; + case g8: + CBoard_piece_move(board, Rook, h8, f8); + break; + case c8: + CBoard_piece_move(board, Rook, a8, d8); + break; + default: + break; + } + } - CBoard_castle_and(board, castling_rights[source]); - CBoard_castle_and(board, castling_rights[target]); - - if (!CBoard_isCheck(board)) { - CBoard_side_switch(board); - return 1; - } else - return 0; - } else { - if (Move_capture(move)) - return Move_make(move, board, 0); - else - return 0; - } + CBoard_castle_and(board, castling_rights[source]); + CBoard_castle_and(board, castling_rights[target]); + + if (!CBoard_isCheck(board)) { + CBoard_side_switch(board); + return 1; + } else + return 0; + } else { + if (Move_capture(move)) + return Move_make(move, board, 0); + else + return 0; + } } /* SEARCHING */ int evaluate(CBoard_T board) { - Square square; - eColor side = CBoard_side(board); - U64 occupancy = CBoard_colorBB(board, side); - - int score = 0; - for (int i = 0; i < 6; i++) { - U64 bitboard = CBoard_pieceBB(board, i); - bitboard_for_each_bit(square, bitboard) { - if (bit_get(occupancy, square)) { - score += Score_value(i); - score += Score_position(i, side, square); - } else { - score -= Score_value(i); - score -= Score_position(i, !side, square); - } + Square square; + eColor side = CBoard_side(board); + U64 occupancy = CBoard_colorBB(board, side); + + int score = 0; + for (int i = 0; i < 6; i++) { + U64 bitboard = CBoard_pieceBB(board, i); + bitboard_for_each_bit(square, bitboard) { + if (bit_get(occupancy, square)) { + score += Score_value(i); + score += Score_position(i, side, square); + } else { + score -= Score_value(i); + score -= Score_position(i, !side, square); + } + } } - } - return score; + return score; } int quiescence(Stats_T stats, CBoard_T board, int alpha, int beta) { - MoveList_T moves; - CBoard_T copy; + MoveList_T moves; + CBoard_T copy; - int eval = evaluate(board); - stats->nodes++; + int eval = evaluate(board); + stats->nodes++; - if (eval >= beta) { - return beta; - } + if (eval >= beta) { + return beta; + } - if (eval > alpha) { - alpha = eval; - } + if (eval > alpha) { + alpha = eval; + } - copy = CBoard_new(); - moves = MoveList_generate(NULL, board); - MoveList_sort(stats, moves); + copy = CBoard_new(); + moves = MoveList_generate(NULL, board); + MoveList_sort(stats, moves); - for (int i = 0; i < MoveList_size(moves); i++) { - CBoard_copy(board, copy); + for (int i = 0; i < MoveList_size(moves); i++) { + CBoard_copy(board, copy); - if (Move_make(MoveList_move(moves, i), copy, 1) == 0) - continue; + if (Move_make(MoveList_move(moves, i), copy, 1) == 0) continue; - stats->ply++; - int score = -quiescence(stats, copy, -beta, -alpha); - stats->ply--; + stats->ply++; + int score = -quiescence(stats, copy, -beta, -alpha); + stats->ply--; - if (score >= beta) { - MoveList_free(&moves); - CBoard_free(&copy); - return beta; - } + if (score >= beta) { + MoveList_free(&moves); + CBoard_free(&copy); + return beta; + } - if (score > alpha) { - alpha = score; + if (score > alpha) { + alpha = score; + } } - } - MoveList_free(&moves); - CBoard_free(&copy); - return alpha; + MoveList_free(&moves); + CBoard_free(&copy); + return alpha; } int negamax(Stats_T stats, CBoard_T board, int alpha, int beta, int depth) { - MoveList_T list; - CBoard_T copy; - int isCheck = 0; - int ply = stats->ply; + MoveList_T list; + CBoard_T copy; + int isCheck = 0; + int ply = stats->ply; - stats->pv_length[ply] = ply; + stats->pv_length[ply] = ply; - if (depth == 0) - return quiescence(stats, board, alpha, beta); + if (depth == 0) return quiescence(stats, board, alpha, beta); - if (ply > MAX_PLY - 1) - return evaluate(board); + if (ply > MAX_PLY - 1) return evaluate(board); - stats->nodes++; + stats->nodes++; - copy = CBoard_new(); - list = MoveList_generate(NULL, board); - isCheck = CBoard_isCheck(board); + copy = CBoard_new(); + list = MoveList_generate(NULL, board); + isCheck = CBoard_isCheck(board); - if (isCheck) - depth++; + if (isCheck) depth++; - int legal_moves = 0; - MoveList_sort(stats, list); - for (int i = 0; i < MoveList_size(list); i++) { - Move move = MoveList_move(list, i); + int legal_moves = 0; + MoveList_sort(stats, list); + for (int i = 0; i < MoveList_size(list); i++) { + Move move = MoveList_move(list, i); - CBoard_copy(board, copy); - if (Move_make(move, copy, 0) == 0) { - continue; - } + CBoard_copy(board, copy); + if (Move_make(move, copy, 0) == 0) { + continue; + } + + stats->ply++; + int score = -negamax(stats, copy, -beta, -alpha, depth - 1); + stats->ply--; + legal_moves++; + + if (score >= beta) { + if (!Move_capture(move)) { + stats->killer_moves[1][ply] = stats->killer_moves[0][ply]; + stats->killer_moves[0][ply] = move; + } + MoveList_free(&list); + CBoard_free(&copy); + return beta; + } + + if (score > alpha) { + if (!Move_capture(move)) + stats->history_moves[Piece_index(Move_piece(move))] + [Move_target(move)] += depth; + alpha = score; - stats->ply++; - int score = -negamax(stats, copy, -beta, -alpha, depth - 1); - stats->ply--; - legal_moves++; - - if (score >= beta) { - if (!Move_capture(move)) { - stats->killer_moves[1][ply] = stats->killer_moves[0][ply]; - stats->killer_moves[0][ply] = move; - } - MoveList_free(&list); - CBoard_free(&copy); - return beta; + 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]; + } } - 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]; + if (legal_moves == 0) { + if (isCheck) + return -49000 + stats->ply; + else + return 0; } - } - - if (legal_moves == 0) { - if (isCheck) - return -49000 + stats->ply; - else - return 0; - } - - MoveList_free(&list); - CBoard_free(&copy); - return alpha; + + MoveList_free(&list); + CBoard_free(&copy); + return alpha; } /* UCI */ 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))); + 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))); } void search_position(CBoard_T board, int depth) { - Stats_T stats = Stats_new(); + Stats_T stats = Stats_new(); - for (int crnt = 1; crnt <= depth; crnt++) { - int score = negamax(stats, board, -50000, 50000, crnt); + for (int crnt = 1; crnt <= depth; crnt++) { + int score = negamax(stats, board, -50000, 50000, crnt); - printf("info score cp %d depth %d nodes %ld pv ", score, crnt, - stats->nodes); + 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]); - printf(" "); + for (int i = 0; i < stats->pv_length[0]; i++) { + Move_print_UCI(stats->pv_table[0][i]); + printf(" "); + } + printf("\n"); } - printf("\n"); - } - printf("bestmove "); - Move_print_UCI(stats->pv_table[0][0]); - printf("\n"); + printf("bestmove "); + Move_print_UCI(stats->pv_table[0][0]); + printf("\n"); - Stats_free(&stats); + Stats_free(&stats); } void print_info(void) { - printf("id name chessTrainer\n"); - printf("id author Dimitrije Dobrota\n"); - printf("uciok\n"); + printf("id name chessTrainer\n"); + printf("id author Dimitrije Dobrota\n"); + printf("uciok\n"); } typedef struct Instruction_T *Instruction_T; struct Instruction_T { - char *command; - char *token; - char *crnt; + char *command; + char *token; + char *crnt; }; char *Instruction_token_next(Instruction_T self); Instruction_T Instruction_new(char *command) { - Instruction_T p; - NEW0(p); - p->command = ALLOC(strlen(command) + 1); - p->token = ALLOC(strlen(command) + 1); - strcpy(p->command, command); - p->crnt = command; - Instruction_token_next(p); - return p; + Instruction_T p; + NEW0(p); + p->command = ALLOC(strlen(command) + 1); + p->token = ALLOC(strlen(command) + 1); + strcpy(p->command, command); + p->crnt = command; + Instruction_token_next(p); + return p; } void Instruction_free(Instruction_T *p) { - FREE((*p)->command); - FREE((*p)->token); - FREE(*p); + FREE((*p)->command); + FREE((*p)->token); + FREE(*p); } char *Instruction_token(Instruction_T self) { return self->token; } char *Instruction_token_n(Instruction_T self, int n) { - while (isspace(*self->crnt) && *self->crnt != '\0') - self->crnt++; + while (isspace(*self->crnt) && *self->crnt != '\0') + self->crnt++; - if (*self->crnt == '\0') { - *self->token = '\0'; - return NULL; - } - - char *p = self->token; - while (n--) { - while (!isspace(*self->crnt) && *self->crnt != '\0' && *self->crnt != ';') - *p++ = *self->crnt++; if (*self->crnt == '\0') { - p++; - break; + *self->token = '\0'; + return NULL; + } + + char *p = self->token; + while (n--) { + while (!isspace(*self->crnt) && *self->crnt != '\0' && + *self->crnt != ';') + *p++ = *self->crnt++; + if (*self->crnt == '\0') { + p++; + break; + } + self->crnt++; + *p++ = ' '; } - self->crnt++; - *p++ = ' '; - } - *--p = '\0'; + *--p = '\0'; - return self->token; + return self->token; } char *Instruction_token_next(Instruction_T self) { - return Instruction_token_n(self, 1); + return Instruction_token_n(self, 1); } Move parse_move(CBoard_T board, char *move_string) { - Move result = 0; - MoveList_T moves; - Square source, target; - - source = coordinates_to_square(move_string); - target = coordinates_to_square(move_string + 2); - - moves = MoveList_generate(NULL, board); - for (int i = 0; i < moves->count; i++) { - Move move = moves->moves[i]; - if (Move_source(move) == source && Move_target(move) == target) { - if (move_string[4]) { - if (tolower(Piece_code(Move_piece_promote(move))) != move_string[4]) - continue; - } - result = move; - break; + Move result = 0; + MoveList_T moves; + Square source, target; + + source = coordinates_to_square(move_string); + target = coordinates_to_square(move_string + 2); + + moves = MoveList_generate(NULL, board); + for (int i = 0; i < moves->count; i++) { + Move move = moves->moves[i]; + if (Move_source(move) == source && Move_target(move) == target) { + if (move_string[4]) { + if (tolower(Piece_code(Move_piece_promote(move))) != + move_string[4]) + continue; + } + result = move; + break; + } } - } - MoveList_free(&moves); - return result; + MoveList_free(&moves); + return result; } CBoard_T Instruction_parse(Instruction_T self, CBoard_T board) { - char *token = Instruction_token(self); + char *token = Instruction_token(self); - if (!board) - board = CBoard_new(); + if (!board) board = CBoard_new(); - do { - if (strcmp(token, "ucinewgame") == 0) { - board = CBoard_fromFEN(board, start_position); - continue; - } + do { + if (strcmp(token, "ucinewgame") == 0) { + board = CBoard_fromFEN(board, start_position); + continue; + } - if (strcmp(token, "quit") == 0) - return NULL; - - if (strcmp(token, "position") == 0) { - token = Instruction_token_next(self); - if (token && strcmp(token, "startpos") == 0) { - board = CBoard_fromFEN(board, start_position); - } else if (token && strcmp(token, "fen") == 0) { - token = Instruction_token_n(self, 6); - board = CBoard_fromFEN(board, token); - } else { - printf("Unknown argument after position\n"); - } - CBoard_print(board); - continue; - } + if (strcmp(token, "quit") == 0) return NULL; + + if (strcmp(token, "position") == 0) { + token = Instruction_token_next(self); + if (token && strcmp(token, "startpos") == 0) { + board = CBoard_fromFEN(board, start_position); + } else if (token && strcmp(token, "fen") == 0) { + token = Instruction_token_n(self, 6); + board = CBoard_fromFEN(board, token); + } else { + printf("Unknown argument after position\n"); + } + CBoard_print(board); + continue; + } - if (strcmp(token, "moves") == 0) { - while ((token = Instruction_token_next(self))) { - Move move = parse_move(board, token); - if (move) { - Move_make(move, board, 0); - } else { - printf("Invalid move %s!\n", token); + if (strcmp(token, "moves") == 0) { + while ((token = Instruction_token_next(self))) { + Move move = parse_move(board, token); + if (move) { + Move_make(move, board, 0); + } else { + printf("Invalid move %s!\n", token); + } + } + CBoard_print(board); + return board; } - } - CBoard_print(board); - return board; - } - if (strcmp(token, "go") == 0) { - token = Instruction_token_next(self); - int depth = 6; - if (token && strcmp(token, "depth") == 0) { - token = Instruction_token_next(self); - depth = atoi(token); - } else { - printf("Unknown argument after go\n"); - } - search_position(board, depth); - continue; - } + if (strcmp(token, "go") == 0) { + token = Instruction_token_next(self); + int depth = 6; + if (token && strcmp(token, "depth") == 0) { + token = Instruction_token_next(self); + depth = atoi(token); + } else { + printf("Unknown argument after go\n"); + } + search_position(board, depth); + continue; + } - if (strcmp(token, "isready") == 0) { - printf("readyok\n"); - continue; - } + if (strcmp(token, "isready") == 0) { + printf("readyok\n"); + continue; + } - if (strcmp(token, "uci") == 0) { - print_info(); - continue; - } + if (strcmp(token, "uci") == 0) { + print_info(); + continue; + } - } while ((token = Instruction_token_next(self))); + } while ((token = Instruction_token_next(self))); - return board; + return board; } void uci_loop(void) { - CBoard_T board = NULL; - Instruction_T instruction; - char input[2000]; - - setbuf(stdin, NULL); - setbuf(stdout, NULL); - - print_info(); - while (1) { - memset(input, 0, sizeof(input)); - fflush(stdout); - if (!fgets(input, sizeof(input), stdin)) - continue; - - instruction = Instruction_new(input); - if (!(board = Instruction_parse(instruction, board))) - break; - Instruction_free(&instruction); - } + CBoard_T board = NULL; + Instruction_T instruction; + char input[2000]; + + setbuf(stdin, NULL); + setbuf(stdout, NULL); + + print_info(); + while (1) { + memset(input, 0, sizeof(input)); + fflush(stdout); + if (!fgets(input, sizeof(input), stdin)) continue; + + instruction = Instruction_new(input); + if (!(board = Instruction_parse(instruction, board))) break; + Instruction_free(&instruction); + } - Instruction_free(&instruction); - CBoard_free(&board); + Instruction_free(&instruction); + CBoard_free(&board); } /* PERFT */ struct MoveList_T moveList[10]; -long nodes; - -void perft_driver(CBoard_T board, struct MoveList_T *moveList, int depth, unsigned long long *nodes) { - if (depth == 0) { - (*nodes)++; - return; - } - - MoveList_T list = MoveList_generate(&moveList[depth], board); - CBoard_T copy = CBoard_new(); - - for (int i = 0; i < MoveList_size(list); i++) { - CBoard_copy(board, copy); - if (!Move_make(MoveList_move(list, i), copy, 0)) - continue; - perft_driver(copy, moveList, depth - 1, nodes); - } - - MoveList_reset(list); - CBoard_free(&copy); +long nodes; + +void perft_driver(CBoard_T board, struct MoveList_T *moveList, int depth, + unsigned long long *nodes) { + if (depth == 0) { + (*nodes)++; + return; + } + + MoveList_T list = MoveList_generate(&moveList[depth], board); + CBoard_T copy = CBoard_new(); + + for (int i = 0; i < MoveList_size(list); i++) { + CBoard_copy(board, copy); + if (!Move_make(MoveList_move(list, i), copy, 0)) continue; + perft_driver(copy, moveList, depth - 1, nodes); + } + + MoveList_reset(list); + CBoard_free(&copy); } void perft_test(CBoard_T board, int depth) { - MoveList_T list = MoveList_generate(&moveList[depth], board); - CBoard_T copy = CBoard_new(); - long start = get_time_ms(); - - printf("\n Performance test\n\n"); - - nodes = 0; - for (int i = 0; i < MoveList_size(list); i++) { - CBoard_copy(board, copy); - Move move = MoveList_move(list, i); - if (!Move_make(MoveList_move(list, i), copy, 0)) continue; - unsigned long long node = 0; - perft_driver(copy, moveList, depth - 1, &node); - printf("%s%s: %llu\n", square_to_coordinates[Move_source(move)], - square_to_coordinates[Move_target(move)], node); - nodes+=node; - } - MoveList_reset(list); - CBoard_free(&copy); - - printf("\nNodes searched: %ld\n\n", nodes); - printf("\n Depth: %d\n", depth); - printf(" Nodes: %ld\n", nodes); - printf(" Time: %ld\n\n", get_time_ms() - start); + MoveList_T list = MoveList_generate(&moveList[depth], board); + CBoard_T copy = CBoard_new(); + long start = get_time_ms(); + + printf("\n Performance test\n\n"); + + nodes = 0; + for (int i = 0; i < MoveList_size(list); i++) { + CBoard_copy(board, copy); + Move move = MoveList_move(list, i); + if (!Move_make(MoveList_move(list, i), copy, 0)) continue; + unsigned long long node = 0; + perft_driver(copy, moveList, depth - 1, &node); + printf("%s%s: %llu\n", square_to_coordinates[Move_source(move)], + square_to_coordinates[Move_target(move)], node); + nodes += node; + } + MoveList_reset(list); + CBoard_free(&copy); + + printf("\nNodes searched: %ld\n\n", nodes); + printf("\n Depth: %d\n", depth); + printf(" Nodes: %ld\n", nodes); + printf(" Time: %ld\n\n", get_time_ms() - start); } - #include <semaphore.h> - #include <pthread.h> +#include <pthread.h> +#include <semaphore.h> typedef struct perf_shared perf_shared; struct perf_shared { - CBoard_T board; - MoveList_T list; - int depth; - sem_t* mutex; - int* index; - sem_t* finish; - unsigned long long *total; + CBoard_T board; + MoveList_T list; + int depth; + sem_t *mutex; + int *index; + sem_t *finish; + unsigned long long *total; }; -void* perft_thread(void *arg) { - perf_shared *shared = (perf_shared *)arg; - CBoard_T board = CBoard_new(); - unsigned long long node_count = 0; +void *perft_thread(void *arg) { + perf_shared *shared = (perf_shared *)arg; + CBoard_T board = CBoard_new(); + unsigned long long node_count = 0; - struct MoveList_T moveList[10]; + struct MoveList_T moveList[10]; - while(1) { - sem_wait(shared->mutex); - *shared->total += node_count; - if(*shared->index >= MoveList_size(shared->list)) { + while (1) { + sem_wait(shared->mutex); + *shared->total += node_count; + if (*shared->index >= MoveList_size(shared->list)) { + sem_post(shared->mutex); + break; + } + Move move = MoveList_move(shared->list, (*shared->index)++); sem_post(shared->mutex); - break; + + CBoard_copy(shared->board, board); + if (!Move_make(move, board, 0)) continue; + + node_count = 0; + perft_driver(board, moveList, shared->depth, &node_count); + printf("%s%s: %llu\n", square_to_coordinates[Move_source(move)], + square_to_coordinates[Move_target(move)], node_count); } - Move move = MoveList_move(shared->list, (*shared->index)++); - sem_post(shared->mutex); - - CBoard_copy(shared->board, board); - if(!Move_make(move, board, 0)) continue; - - node_count = 0; - perft_driver(board, moveList, shared->depth, &node_count); - printf("%s%s: %llu\n", square_to_coordinates[Move_source(move)], - square_to_coordinates[Move_target(move)], node_count); - } - CBoard_free(&board); - sem_post(shared->finish); - return NULL; + CBoard_free(&board); + sem_post(shared->finish); + return NULL; } void perft_test_threaded(CBoard_T board, int depth) { - MoveList_T list = MoveList_generate(NULL, board); - int size = 8; - - unsigned long long total = 0; - perf_shared shared[size]; - pthread_t threads[size]; - sem_t mutex, finish; - - - int index = 0; - sem_init(&mutex, 0, 1); - sem_init(&finish, 0, 0); - for(int i=0; i<size; i++) { - shared[i].board = board; - shared[i].list = list; - shared[i].depth = depth - 1; - shared[i].mutex = &mutex; - shared[i].index = &index; - shared[i].finish = &finish; - shared[i].total = &total; - pthread_create(threads + i, NULL, perft_thread, (void *)(shared + i)); - } - - for(int i=0; i<size; i++) sem_wait(&finish); - MoveList_free(&list); - - printf("Nodes processed: %llu\n", total); + MoveList_T list = MoveList_generate(NULL, board); + int size = 8; + + unsigned long long total = 0; + perf_shared shared[size]; + pthread_t threads[size]; + sem_t mutex, finish; + + int index = 0; + sem_init(&mutex, 0, 1); + sem_init(&finish, 0, 0); + for (int i = 0; i < size; i++) { + shared[i].board = board; + shared[i].list = list; + shared[i].depth = depth - 1; + shared[i].mutex = &mutex; + shared[i].index = &index; + shared[i].finish = &finish; + shared[i].total = &total; + pthread_create(threads + i, NULL, perft_thread, (void *)(shared + i)); + } + + for (int i = 0; i < size; i++) + sem_wait(&finish); + MoveList_free(&list); + + printf("Nodes processed: %llu\n", total); } /* MAIN */ void init_all() { - init_leapers_attacks(); - init_sliders_attacks(); + init_leapers_attacks(); + init_sliders_attacks(); } - int main(void) { - init_all(); - - CBoard_T board = NULL; - board = CBoard_fromFEN(board, start_position); - CBoard_print(board); - //perft_test(board, 7); - perft_test_threaded(board, 7); - CBoard_free(&board); - return 0; + init_all(); + + CBoard_T board = NULL; + board = CBoard_fromFEN(board, start_position); + CBoard_print(board); + // perft_test(board, 7); + perft_test_threaded(board, 7); + CBoard_free(&board); + return 0; } diff --git a/src/utils.c b/src/utils.c @@ -38,50 +38,48 @@ const char *square_to_coordinates[]={ // clang-format on // Square coordinates_to_square(char *cord) { - return (cord[1] - '1') * 8 + (cord[0] - 'a'); + return (cord[1] - '1') * 8 + (cord[0] - 'a'); } int bit_count(U64 bitboard) { - int count = 0; + int count = 0; - while (bitboard > 0) { - count++; - bitboard &= bitboard - 1; - } + while (bitboard > 0) { + count++; + bitboard &= bitboard - 1; + } - return count; + return count; } int bit_lsb_index(U64 bitboard) { - if (!bitboard) - return -1; + if (!bitboard) return -1; - return bit_count((bitboard & -bitboard) - 1); + return bit_count((bitboard & -bitboard) - 1); } void bitboard_print(U64 bitboard) { - for (int rank = 0; rank < 8; rank++) { - for (int file = 0; file < 8; file++) { - Square square = (7 - rank) * 8 + file; + for (int rank = 0; rank < 8; rank++) { + for (int file = 0; file < 8; file++) { + Square square = (7 - rank) * 8 + file; - if (!file) - printf(" %d ", 8 - rank); + if (!file) printf(" %d ", 8 - rank); - printf("%d ", bit_get(bitboard, square) ? 1 : 0); + printf("%d ", bit_get(bitboard, square) ? 1 : 0); + } + printf("\n"); } - printf("\n"); - } - printf("\n A B C D E F G H\n\n"); - printf(" Bitboard: %llud\n\n", bitboard); + printf("\n A B C D E F G H\n\n"); + printf(" Bitboard: %llud\n\n", bitboard); } int get_time_ms(void) { #ifdef WIN64 - return GetTickCount(); + return GetTickCount(); #else - struct timeval time; - gettimeofday(&time, NULL); - return time.tv_sec * 1000 + time.tv_usec / 1000; + struct timeval time; + gettimeofday(&time, NULL); + return time.tv_sec * 1000 + time.tv_usec / 1000; #endif }