summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.h2
-rw-r--r--src/main.c101
2 files changed, 81 insertions, 22 deletions
diff --git a/src/config.h b/src/config.h
index 60d60c3..5da6a21 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,2 +1,4 @@
#define BOARD_SIZE 8
#define DEFAULT_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
+#define MAX_DEPTH 5
+#define INFINITY 1000000
diff --git a/src/main.c b/src/main.c
index 644e869..8181d7c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,6 +5,9 @@
#include "config.h"
#include "pieces.h"
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
void print_board(int board[128]) {
for (int rank = 7; rank >= 0; rank--) {
@@ -150,12 +153,12 @@ int validate_move(int move[2], int color, int* board) {
int target_piece = board[square];
if (square == destination) {
- if (target_piece & color) return -4;
+ if (target_piece != EMPTY && target_piece % 2 == color) return -4;
return target_piece;
}
if (target_piece != EMPTY) break;
- if ((piece & NO_COLOR) == PAWN || (piece & NO_COLOR) == KNIGHT || piece == KING) break;
+ if ((piece & NO_COLOR) == PAWN || (piece & NO_COLOR) == KNIGHT || (piece & NO_COLOR) == KING) break;
}
legal_move++;
}
@@ -187,7 +190,35 @@ int apply_move(int move[2], int* board) {
return board[destination];
}
-int compute_advantage(int* board, int color) {
+
+int evaluate_pawn(int piece, int rank) {
+ int color = piece % 2;
+ if (color == 0) {
+ switch (rank) {
+ case 7:
+ return 9;
+ case 6:
+ return 5;
+ case 5:
+ return 3;
+ default:
+ return 1;
+ }
+ } else {
+ switch (rank) {
+ case 0:
+ return 9;
+ case 1:
+ return 5;
+ case 2:
+ return 3;
+ default:
+ return 1;
+ }
+ }
+}
+
+int compute_material_advantage(int* board, int color) {
int counter = 0;
for (int rank = 7; rank >= 0; rank--) {
for (int file = 0; file < 8; file++) {
@@ -195,6 +226,12 @@ int compute_advantage(int* board, int color) {
if (piece != EMPTY) {
int sign = (piece % 2 == color) ? 1 : -1;
switch (piece & NO_COLOR) {
+ case KING:
+ counter += 1000 * sign;
+ break;
+ case PAWN:
+ counter += evaluate_pawn(piece, rank) * sign;
+ break;
case KNIGHT:
counter += 3 * sign;
break;
@@ -217,10 +254,15 @@ int compute_advantage(int* board, int color) {
return counter;
}
-void find_best_move(int best_move[2], int* board, int color, int depth) {
+// 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* board, int color, int depth, int alpha, int beta) {
+ int best_move[2];
int fake_board[128];
- int best_advantage = -10000;
-
+ int is_maximizer = (color == 0);
+ int best_value = is_maximizer ? -INFINITY : INFINITY;
for (int rank = 7; rank >= 0; rank--) {
for (int file = 0; file < 8; file++) {
@@ -231,6 +273,7 @@ void find_best_move(int best_move[2], int* board, int color, int depth) {
for (int file_destination = 0; file_destination < 8; file_destination++) {
int index_destination = rank_destination * 16 + file_destination;
int move[2] = { index, index_destination };
+
if (validate_move(move, color, board) >= 0) {
// Generate fake board
for (int r = 7; r >= 0; r--) {
@@ -239,20 +282,31 @@ void find_best_move(int best_move[2], int* board, int color, int depth) {
}
}
+
apply_move(move, fake_board);
- // Try finding a response
- if (depth) {
- int response_move[2];
- find_best_move(response_move, fake_board, color ^ 1, depth - 1);
- apply_move(response_move, fake_board);
+ int value = depth < MAX_DEPTH
+ ? find_best_move(fake_board, 1 - color, depth + 1, alpha, beta)
+ : compute_material_advantage(fake_board, 0); // Always for maximizer (white)
+
+ 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);
+ } else {
+ if (value < best_value) {
+ best_value = value;
+ best_move[0] = move[0];
+ best_move[1] = move[1];
+ }
+ beta = MIN(best_value, beta);
}
- int advantage = compute_advantage(fake_board, color);
- if (advantage > best_advantage) {
- best_advantage = advantage;
- best_move[0] = move[0];
- best_move[1] = move[1];
+ if (beta <= alpha) {
+ return best_value;
}
}
}
@@ -261,10 +315,13 @@ void find_best_move(int best_move[2], int* board, int color, int depth) {
}
}
- char move_in_notation[] = "xy XY";
- index_to_notation(best_move[0], move_in_notation);
- index_to_notation(best_move[1], move_in_notation + 3);
- if (depth == 3) printf("Best move for %i is %s with score %i\n", color, move_in_notation, best_advantage);
+ if (depth == 0) {
+ char move_in_notation[] = "xy XY";
+ index_to_notation(best_move[0], move_in_notation);
+ index_to_notation(best_move[1], move_in_notation + 3);
+ printf("Best move (validation: %i) for %s is %s with score %i in #%i moves\n", validate_move(best_move, color, board), COLORS[color], move_in_notation, best_value, MAX_DEPTH);
+ }
+ return best_value;
}
int main() {
@@ -277,8 +334,8 @@ int main() {
int color = 0;
while (1) {
- printf("Current board advantage is %i\n", compute_advantage(board, color));
- find_best_move(move, board, color, 3);
+ printf("Current board advantage is %i\n", compute_material_advantage(board, 0));
+ find_best_move(board, color, 0, -INFINITY, +INFINITY);
printf("Enter a move for %s:\n", COLORS[color]);
input_move(move);