diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-08-19 16:26:19 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-08-19 16:40:01 +0300 |
commit | 50430eb61a3056332ae31597729fba4f0cd26e5d (patch) | |
tree | 8a76ed66710518b844dd0fe5a6b1ac638b46b56b | |
parent | de8f4f261f970f33f360662eb2dee0e03faaf301 (diff) | |
download | c-chess-50430eb61a3056332ae31597729fba4f0cd26e5d.tar.gz |
refactor: separate structure for Move
-rw-r--r-- | src/main.c | 145 | ||||
-rw-r--r-- | src/structs.h | 6 |
2 files changed, 74 insertions, 77 deletions
@@ -6,6 +6,7 @@ #include "config.h" #include "pieces.h" +#include "structs.h" #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) @@ -96,14 +97,15 @@ void index_to_notation(int index, char notation[2]) { notation[1] = (index >> 4) + '1'; } -void print_move(int move[2]) { +void print_move(Move move) { char move_in_notation[] = "xy XY"; - index_to_notation(move[0], move_in_notation); - index_to_notation(move[1], move_in_notation + 3); + index_to_notation(move.origin, move_in_notation); + index_to_notation(move.destination, move_in_notation + 3); printf("%s\n", move_in_notation); }; -void input_move(int move[2]) { +Move input_move() { + Move move; char file; int rank; char file_destination; @@ -111,17 +113,15 @@ void input_move(int move[2]) { scanf(" %c%i %c%i", &file, &rank, &file_destination, &rank_destination); - move[0] = notation_to_index(file, rank); - move[1] = notation_to_index(file_destination, rank_destination); + move.origin = notation_to_index(file, rank); + move.destination = notation_to_index(file_destination, rank_destination); + return move; }; -int validate_move(int move[2], int color, int* board) { - int origin = move[0]; - int destination = move[1]; +int validate_move(Move move, int color, int* board) { + if ((move.origin & 0x88) || (move.destination & 0x88)) return -1; - if ((origin & 0x88) || (destination & 0x88)) return -1; - - int piece = board[origin]; + int piece = board[move.origin]; int* legal_move; if (piece % 2 != color) return -3; @@ -144,12 +144,12 @@ int validate_move(int move[2], int color, int* board) { break; case PAWN: if (piece & BLACK) { - if (board[destination] != EMPTY) legal_move = blackPawnAttackMoves; - else if (origin >> 4 == 6) legal_move = newBlackPawnMoves; + if (board[move.destination] != EMPTY) legal_move = blackPawnAttackMoves; + else if (move.origin >> 4 == 6) legal_move = newBlackPawnMoves; else legal_move = blackPawnMoves; } else { - if (board[destination] != EMPTY) legal_move = pawnAttackMoves; - else if (origin >> 4 == 1) legal_move = newPawnMoves; + if (board[move.destination] != EMPTY) legal_move = pawnAttackMoves; + else if (move.origin >> 4 == 1) legal_move = newPawnMoves; else legal_move = pawnMoves; } break; @@ -158,10 +158,10 @@ int validate_move(int move[2], int color, int* board) { } while(*legal_move) { - for (int square = origin + *legal_move; !(square & 0x88); square += *legal_move) { + for (int square = move.origin + *legal_move; !(square & 0x88); square += *legal_move) { int target_piece = board[square]; - if (square == destination) { + if (square == move.destination) { if (target_piece != EMPTY && target_piece % 2 == color) return -4; return target_piece; } @@ -174,25 +174,25 @@ int validate_move(int move[2], int color, int* board) { // Handle castling if ((piece & NO_COLOR) == KING) { - if (piece % 2 == WHITE && origin == 4) { - if (destination == 2) { + if (piece % 2 == WHITE && move.origin == 4) { + if (move.destination == 2) { for (int i = 1; i < 4; i++) { if (board[i] != EMPTY) return -5; } return 0; - } else if (destination == 6) { + } else if (move.destination == 6) { for (int i = 5; i < 7; i++) { if (board[i] != EMPTY) return -5; } return 0; } - } else if (piece % 2 == BLACK && origin == 116) { - if (destination == 114) { + } else if (piece % 2 == BLACK && move.origin == 116) { + if (move.destination == 114) { for (int i = 114; i < 116; i++) { if (board[i] != EMPTY) return -5; } return 0; - } else if (destination == 118) { + } else if (move.destination == 118) { for (int i = 117; i < 119; i++) { if (board[i] != EMPTY) return -5; } @@ -213,34 +213,32 @@ char* VALIDATION_ERRORS[] = { "castle is not allowed", }; -int apply_move(int move[2], int* board) { - int origin = move[0]; - int destination = move[1]; - int piece = board[origin]; - int target_piece = board[destination]; +int apply_move(Move move, int* board) { + int piece = board[move.origin]; + int target_piece = board[move.destination]; - board[destination] = piece; - board[origin] = EMPTY; + board[move.destination] = piece; + board[move.origin] = EMPTY; if (target_piece != EMPTY) { // printf("Captured %s\n", pieces[target_piece]); } - if ((piece & NO_COLOR) == KING && abs(destination - origin) == 2) { + if ((piece & NO_COLOR) == KING && abs(move.destination - move.origin) == 2) { // CASTLE! - if (destination == 2) { + if (move.destination == 2) { int rook = board[0]; board[0] = EMPTY; board[3] = rook; - } else if (destination == 6) { + } else if (move.destination == 6) { int rook = board[7]; board[7] = EMPTY; board[5] = rook; - } else if (destination == 114) { + } else if (move.destination == 114) { int rook = board[112]; board[112] = EMPTY; board[115] = rook; - } else if (destination == 118) { + } else if (move.destination == 118) { int rook = board[119]; board[119] = EMPTY; board[117] = rook; @@ -250,29 +248,27 @@ int apply_move(int move[2], int* board) { return target_piece; } -void reverse_move(int move[2], int captured_piece, int* board) { - int origin = move[0]; - int destination = move[1]; - int piece = board[destination]; +void reverse_move(Move move, int captured_piece, int* board) { + int piece = board[move.destination]; - board[origin] = piece; - board[destination] = captured_piece; + board[move.origin] = piece; + board[move.destination] = captured_piece; - if ((piece & NO_COLOR) == KING && abs(destination - origin) == 2) { + if ((piece & NO_COLOR) == KING && abs(move.destination - move.origin) == 2) { // CASTLE! - if (destination == 2) { + if (move.destination == 2) { int rook = board[3]; board[3] = EMPTY; board[0] = rook; - } else if (destination == 6) { + } else if (move.destination == 6) { int rook = board[5]; board[5] = EMPTY; board[7] = rook; - } else if (destination == 114) { + } else if (move.destination == 114) { int rook = board[115]; board[115] = EMPTY; board[112] = rook; - } else if (destination == 118) { + } else if (move.destination == 118) { int rook = board[117]; board[117] = EMPTY; board[119] = rook; @@ -411,13 +407,17 @@ int compute_score(int* board) { return compute_material_advantage(board, WHITE)* 3 + coverage_score; } -// Alpha-beta pruning -// Value here is white material advantage over black -// Alpha is the best value for maximizer (white) -// Beta is the best value for minimizer (black) -int find_best_move(int best_move[2], int* board, int color, int depth, int alpha, int beta, int* metrics) { +/* + * Alpha-beta pruning + * Value here is white material advantage over black + * Alpha is the best value for maximizer (white) + * Beta is the best value for minimizer (black) + */ +Move find_best_move(int* board, int color, int depth, int alpha, int beta, int* metrics) { int is_maximizer = (color == 0); - int best_value = is_maximizer ? -INFINITY : INFINITY; + + Move best_move; + best_move.value = is_maximizer ? -INFINITY : INFINITY; for (int rank = 7; rank >= 0; rank--) { for (int file = 0; file < 8; file++) { @@ -427,38 +427,29 @@ int find_best_move(int best_move[2], int* board, int color, int depth, int alpha for (int rank_destination = 7; rank_destination >= 0; rank_destination--) { for (int file_destination = 0; file_destination < 8; file_destination++) { int index_destination = rank_destination * 16 + file_destination; - int move[2] = { index, index_destination }; + Move move = { index, index_destination }; if (validate_move(move, color, board) >= 0) { *metrics += 1; int captured_piece = apply_move(move, board); - int dummy[2]; - int value = depth < MAX_DEPTH - ? find_best_move(dummy, board, 1 - color, depth + 1, alpha, beta, metrics) + move.value = depth < MAX_DEPTH + ? find_best_move(board, 1 - color, depth + 1, alpha, beta, metrics).value : compute_score(board); reverse_move(move, captured_piece, board); if (is_maximizer) { - if (value > best_value) { - best_value = value; - best_move[0] = move[0]; - best_move[1] = move[1]; - } - alpha = MAX(best_value, alpha); + if (move.value > best_move.value) best_move = move; + alpha = MAX(best_move.value, alpha); } else { - if (value < best_value) { - best_value = value; - best_move[0] = move[0]; - best_move[1] = move[1]; - } - beta = MIN(best_value, beta); + if (move.value < best_move.value) best_move = move; + beta = MIN(best_move.value, beta); } if (beta <= alpha) { - return best_value; + return best_move; } } } @@ -467,7 +458,7 @@ int find_best_move(int best_move[2], int* board, int color, int depth, int alpha } } - return best_value; + return best_move; } int main() { @@ -476,7 +467,7 @@ int main() { print_board(board); - int move[2]; + Move move; int color = WHITE; while (1) { @@ -484,19 +475,19 @@ int main() { printf("Current score is %i\n", compute_score(board)); printf("White coverage: %i, black coverage: %i\n", compute_coverage(board, WHITE), compute_coverage(board, BLACK)); printf("Enter a move for %s:\n", COLORS[color]); - input_move(move); + move = input_move(); } else { printf("Evaluating move for %s...\n", COLORS[color]); clock_t start, end; int metrics = 0; start = clock(); - int value = find_best_move(move, board, color, 0, -INFINITY, +INFINITY, &metrics); + move = find_best_move(board, color, 0, -INFINITY, +INFINITY, &metrics); end = clock(); char move_in_notation[] = "xy XY"; - index_to_notation(move[0], move_in_notation); - index_to_notation(move[1], move_in_notation + 3); + index_to_notation(move.origin, move_in_notation); + index_to_notation(move.destination, move_in_notation + 3); printf("[%i positions analyzed in %f seconds]\n", metrics, (double)(end - start) / CLOCKS_PER_SEC); - printf("Best move for black is %s with score %i in #%i moves\n", move_in_notation, value, MAX_DEPTH); + printf("Best move for black is %s with score %i in #%i moves\n", move_in_notation, move.value, MAX_DEPTH); } int error = validate_move(move, color, board); diff --git a/src/structs.h b/src/structs.h new file mode 100644 index 0000000..643e7f2 --- /dev/null +++ b/src/structs.h @@ -0,0 +1,6 @@ +typedef struct { + int origin; + int destination; + int value; // Estimated move value +} Move; + |