summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-08-19 16:26:19 +0300
committereug-vs <eugene@eug-vs.xyz>2022-08-19 16:40:01 +0300
commit50430eb61a3056332ae31597729fba4f0cd26e5d (patch)
tree8a76ed66710518b844dd0fe5a6b1ac638b46b56b
parentde8f4f261f970f33f360662eb2dee0e03faaf301 (diff)
downloadc-chess-50430eb61a3056332ae31597729fba4f0cd26e5d.tar.gz
refactor: separate structure for Move
-rw-r--r--src/main.c145
-rw-r--r--src/structs.h6
2 files changed, 74 insertions, 77 deletions
diff --git a/src/main.c b/src/main.c
index 2174f97..a8f7038 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
+