return moves;
}
// clang-format off
const int castling_rights[64] = {
13, 15, 15, 15, 12, 15, 15, 14,
15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15,
7, 15, 15, 15, 3, 15, 15, 11,
};
// clang-format on
int make_move(CBoard_T cboard, Move move, int flag) {
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(cboard);
eColor color = CBoard_side(board);
if (!Move_capture(move))
CBoard_piece_move(cboard, Piece, source, target);
CBoard_piece_move(board, Piece, source, target);
else
CBoard_piece_capture(cboard, Piece, source, target);
CBoard_piece_capture(board, Piece, source, target);
if (Move_promote(move)) {
Piece_T Promote = Piece_fromIndex(Move_promote(move));
CBoard_piece_pop(cboard, Piece, target);
CBoard_piece_set(cboard, Promote, target);
CBoard_piece_pop(board, Piece, target);
CBoard_piece_set(board, Move_promote(move), target);
}
{
int ntarget = target + (color == WHITE ? -8 : +8);
if (Move_enpassant(move))
CBoard_piece_pop(cboard, Piece_get(PAWN, !color), ntarget);
CBoard_piece_pop(board, Piece_get(PAWN, !color), ntarget);
CBoard_enpassant_set(cboard, 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(cboard));
Piece_T Rook = Piece_get(ROOK, CBoard_side(board));
switch (target) {
case g1: CBoard_piece_move(cboard, Rook, h1, f1); break;
case c1: CBoard_piece_move(cboard, Rook, a1, d1); break;
case g8: CBoard_piece_move(cboard, Rook, h8, f8); break;
case c8: CBoard_piece_move(cboard, Rook, a8, d8); break;
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(cboard, castling_rights[source]);
CBoard_castle_and(cboard, castling_rights[target]);
CBoard_castle_and(board, castling_rights[source]);
CBoard_castle_and(board, castling_rights[target]);
if (!CBoard_isCheck(cboard)) {
CBoard_side_switch(cboard);
if (!CBoard_isCheck(board)) {
CBoard_side_switch(board);
return 1;
} else
return 0;
} else {
if (Move_capture(move))
return make_move(cboard, move, 0);
return Move_make(move, board, 0);
else
return 0;
}
}
long nodes = 0;
struct MoveList_T moveList[10];
void perft_driver(CBoard_T self, int depth) {
if (depth == 0) {
nodes++;
return;
}
MoveList_T moves = generate_moves(self, &moveList[depth]);
CBoard_T copy = CBoard_new();
for (int i = 0; i < moves->count; i++) {
CBoard_copy(self, copy);
if (!make_move(copy, moves->moves[i], 0))
continue;
perft_driver(copy, depth - 1);
}
moveList[depth].count = 0;
}
void perft_test(CBoard_T self, int depth) {
MoveList_T moves = generate_moves(self, &moveList[depth]);
CBoard_T copy = CBoard_new();
long start = get_time_ms();
printf("\n Performance test\n\n");
for (int i = 0; i < moves->count; i++) {
CBoard_copy(self, copy);
if (!make_move(copy, moves->moves[i], 0))
continue;
long cummulative_nodes = nodes;
perft_driver(copy, depth - 1);
long old_nodes = nodes - cummulative_nodes;
printf("%s%s: %ld\n", square_to_coordinates[Move_source(moves->moves[i])],
square_to_coordinates[Move_target(moves->moves[i])], old_nodes);
}
printf("\nNodes searched: %ld\n\n", nodes);
return;
printf("\n Depth: %d\n", depth);
printf(" Nodes: %ld\n", nodes);
printf(" Time: %ld\n\n", get_time_ms() - start);
}
void init_all() {
init_leapers_attacks();
init_sliders_attacks();
}
/* UCI */
struct Score_T {
int value;
int score[64];
int capture[6];
};
// clang-format off
struct Score_T Scores[] = {
[PAWN] = {
.value = 100,
.score = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, -10, -10, 0, 0, 0,
0, 0, 0, 5, 5, 0, 0, 0,
5, 5, 10, 20, 20, 5, 5, 5,
10, 10, 10, 20, 20, 10, 10, 10,
20, 20, 20, 30, 30, 30, 20, 20,
30, 30, 30, 40, 40, 30, 30, 30,
90, 90, 90, 90, 90, 90, 90, 90, },
.capture = { [PAWN] = 105, [KNIGHT] = 205,
[BISHOP] = 305, [ROOK] = 405,
[QUEEN] = 505, [KING] = 605} },
[KNIGHT] = {
.value = 300,
.score = {
-5, -10 , 0, 0, 0, 0, -10, -5,
-5, 0, 0, 0, 0, 0, 0, -5,
-5, 5, 20, 10, 10, 20, 5, -5,
-5, 10, 20, 30, 30, 20, 10, -5,
-5, 10, 20, 30, 30, 20, 10, -5,
-5, 5, 20, 20, 20, 20, 5, -5,
-5, 0, 0, 10, 10, 0, 0, -5,
-5, 0, 0, 0, 0, 0, 0, -5, },
.capture = { [PAWN] = 104, [KNIGHT] = 204,
[BISHOP] = 304, [ROOK] = 404,
[QUEEN] = 504, [KING] = 604} },
[BISHOP] = {
.value = 350,
.score = {
0, 0, -10, 0, 0, -10, 0, 0,
0, 30, 0, 0, 0, 0, 30, 0,
0, 10, 0, 0, 0, 0, 10, 0,
0, 0, 10, 20, 20, 10, 0, 0,
0, 0, 10, 20, 20, 10, 0, 0,
0, 0, 0, 10, 10, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, },
.capture = { [PAWN] = 103, [KNIGHT] = 203,
[BISHOP] = 303, [ROOK] = 403,
[QUEEN] = 503, [KING] = 603} },
[ROOK] = {
.value = 500,
.score = {
0, 0, 0, 20, 20, 0, 0, 0,
0, 0, 10, 20, 20, 10, 0, 0,
0, 0, 10, 20, 20, 10, 0, 0,
0, 0, 10, 20, 20, 10, 0, 0,
0, 0, 10, 20, 20, 10, 0, 0,
0, 0, 10, 20, 20, 10, 0, 0,
50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, },
.capture = { [PAWN] = 102, [KNIGHT] = 202,
[BISHOP] = 302, [ROOK] = 402,
[QUEEN] = 502, [KING] = 602} },
[QUEEN] = {
.value = 1000,
.score = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, },
.capture = { [PAWN] = 101, [KNIGHT] = 201,
[BISHOP] = 301, [ROOK] = 401,
[QUEEN] = 501, [KING] = 601} },
[KING] = {
.value = 10000,
.score = {
0, 0, 5, 0, -15, 0, 10, 0,
0, 5, 5, -5, -5, 0, 5, 0,
0, 0, 5, 10, 10, 5, 0, 0,
0, 5, 10, 20, 20, 10, 5, 0,
0, 5, 10, 20, 20, 10, 5, 0,
0, 5, 5, 10, 10, 5, 5, 0,
0, 0, 5, 5, 5, 5, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, },
.capture = { [PAWN] = 100, [KNIGHT] = 200,
[BISHOP] = 300, [ROOK] = 400,
[QUEEN] = 500, [KING] = 600} },
};
const int mirror_score[128] =
{
a8, b8, c8, d8, e8, f8, g8, h8,
a7, b7, c7, d7, e7, f7, g7, h7,
a6, b6, c6, d6, e6, f6, g6, h6,
a5, b5, c5, d5, e5, f5, g5, h5,
a4, b4, c4, d4, e4, f4, g4, h4,
a3, b3, c3, d3, e3, f3, g3, h3,
a2, b2, c2, d2, e2, f2, g2, h2,
a1, b1, c1, d1, e1, f1, g1, h1, no_sq,
};
// clang-format on
int Score_value(ePiece piece) { return Scores[piece].value; }
int Score_score(ePiece piece, eColor color, Square square) {
if (color == BLACK)
square = mirror_score[square];
return Scores[piece].score[square];
}
/* SEARCHING */
int evaluate(CBoard_T board) {
Square square;