summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/main.c2
-rw-r--r--include/othello_board.h2
-rw-r--r--include/othello_move.h9
-rw-r--r--src/board.c28
-rw-r--r--src/game_loop.c21
-rw-r--r--src/move.c47
6 files changed, 87 insertions, 22 deletions
diff --git a/cmd/main.c b/cmd/main.c
index 5863889..47df351 100644
--- a/cmd/main.c
+++ b/cmd/main.c
@@ -118,7 +118,7 @@ int main(int argc, char **argv) {
}
puts("Here was the final board:");
- print_board(get_board());
+ print_board(get_board(), NULL, 0);
printf("Final white score: %d\n", white_score);
printf("Final black score: %d\n", black_score);
diff --git a/include/othello_board.h b/include/othello_board.h
index 99ad839..a8299fc 100644
--- a/include/othello_board.h
+++ b/include/othello_board.h
@@ -32,7 +32,7 @@ enum player_color **copy_board(enum player_color **board);
void free_board(enum player_color **board);
// Prints the current state of the board, including coordinates in the margins.
-void print_board(enum player_color **board);
+void print_board(enum player_color **board, struct move *highlighted_moves, size_t highlighted_moves_length);
void scm_print_board(SCM board);
// Returns the current board.
diff --git a/include/othello_move.h b/include/othello_move.h
index a1f030d..6b58bbe 100644
--- a/include/othello_move.h
+++ b/include/othello_move.h
@@ -22,7 +22,9 @@
#include "othello.h"
-struct move prompt_get_move(enum player_color current_player);
+struct move prompt_get_move(enum player_color current_player,
+ struct move *flipped_last_turn,
+ size_t flipped_last_turn_length);
struct move get_scm_move(char *strategy_path);
// True if move is valid for current_player.
@@ -41,8 +43,9 @@ bool has_valid_moves(enum player_color **board,
// Returns non-zero number if the move was valid.
// Returns the number of flipped tiles.
-int apply_move(enum player_color **board, enum player_color current_player,
- struct move move);
+size_t apply_move(enum player_color **board, enum player_color current_player,
+ struct move move, struct move **flipped_spots,
+ size_t *flipped_spots_capacity);
// Does not actually modify the current board state. Returns a new board with
// the move applied. If the move was not valid, an empty list (nil) is returned.
SCM scm_apply_move(SCM move, SCM board, SCM current_player);
diff --git a/src/board.c b/src/board.c
index 54340e0..315cafe 100644
--- a/src/board.c
+++ b/src/board.c
@@ -156,14 +156,36 @@ enum player_color **scm_board_to_c_board(SCM scm_board) {
return board;
}
-void print_board(enum player_color **board) {
+void print_board(enum player_color **board, struct move *highlighted_moves,
+ size_t highlighted_moves_length) {
puts(" 0 1 2 3 4 5 6 7");
for (int row = 0; row < 8; row++) {
printf("%d ", row);
for (int col = 0; col < 8; col++) {
- printf("%c ", board[row][col]);
+ bool should_highlight = false;
+ for (size_t i = 0; !should_highlight && i < highlighted_moves_length;
+ i++) {
+ if (highlighted_moves[i].row == row &&
+ highlighted_moves[i].col == col) {
+ should_highlight = true;
+ }
+ }
+ if (!should_highlight) {
+ printf("%c ", board[row][col]);
+ } else {
+ switch (board[row][col]) {
+ case WHITE:
+ printf("W ");
+ break;
+ case BLACK:
+ printf("B ");
+ break;
+ case EMPTY:
+ printf("* ");
+ }
+ }
}
printf("\n");
}
@@ -173,5 +195,5 @@ void scm_print_board(SCM scm_board) {
enum player_color **board =
SCM_UNBNDP(scm_board) ? get_board() : scm_board_to_c_board(scm_board);
- print_board(board);
+ print_board(board, NULL, 0);
}
diff --git a/src/game_loop.c b/src/game_loop.c
index 2af20bd..cc20454 100644
--- a/src/game_loop.c
+++ b/src/game_loop.c
@@ -67,12 +67,15 @@ enum player_color scm_player_to_c_player(SCM player) {
static struct move current_player_move(enum player_color current_player,
char *player_one_strategy_path,
- char *player_two_strategy_path) {
+ char *player_two_strategy_path,
+ struct move *flipped_by_last_turn,
+ size_t flipped_by_last_turn_length) {
struct move move = {-1, -1};
if ((current_player == WHITE && player_one_strategy_path == NULL) ||
(current_player == BLACK && player_two_strategy_path == NULL)) {
- move = prompt_get_move(current_player);
+ move = prompt_get_move(current_player, flipped_by_last_turn,
+ flipped_by_last_turn_length);
} else if (current_player == WHITE) {
move = get_scm_move(player_one_strategy_path);
} else if (current_player == BLACK) {
@@ -93,10 +96,18 @@ enum player_color game_loop(char *player_one_strategy_path,
current_player = WHITE;
+ struct move *flipped_by_last_turn = malloc(sizeof(struct move));
+ size_t flipped_by_last_turn_length = 0;
+ size_t flipped_by_last_turn_capacity = 1;
+
while (has_valid_moves(get_board(), current_player)) {
struct move move = current_player_move(
- current_player, player_one_strategy_path, player_two_strategy_path);
- if (apply_move(get_board(), current_player, move)) {
+ current_player, player_one_strategy_path, player_two_strategy_path,
+ flipped_by_last_turn, flipped_by_last_turn_length);
+
+ if ((flipped_by_last_turn_length = apply_move(
+ get_board(), current_player, move, &flipped_by_last_turn,
+ &flipped_by_last_turn_capacity))) {
current_player = other_player;
}
}
@@ -105,6 +116,8 @@ enum player_color game_loop(char *player_one_strategy_path,
rl_clear_history();
}
+ free(flipped_by_last_turn);
+
return get_winner(get_board(), current_player, white_score, black_score);
}
diff --git a/src/move.c b/src/move.c
index 2f96ca3..9f8df44 100644
--- a/src/move.c
+++ b/src/move.c
@@ -36,8 +36,10 @@ static void print_help() {
"p - Print the board again\n");
}
-static char *prompt_player(enum player_color current_player) {
- print_board(get_board());
+static char *prompt_player(enum player_color current_player,
+ struct move *flipped_last_turn,
+ size_t flipped_last_turn_length) {
+ print_board(get_board(), flipped_last_turn, flipped_last_turn_length);
switch (current_player) {
case WHITE:
return "Player 1 [h for help] > ";
@@ -49,11 +51,14 @@ static char *prompt_player(enum player_color current_player) {
}
}
-struct move prompt_get_move(enum player_color current_player) {
+struct move prompt_get_move(enum player_color current_player,
+ struct move *flipped_last_turn,
+ size_t flipped_last_turn_length) {
// Initialize move to an invalid move.
struct move move = {-1, -1};
- char *prompt = prompt_player(current_player);
+ char *prompt = prompt_player(current_player, flipped_last_turn,
+ flipped_last_turn_length);
do {
char *input = readline(prompt);
@@ -64,7 +69,7 @@ struct move prompt_get_move(enum player_color current_player) {
if (STREQ(input, "h")) {
print_help();
} else if (STREQ(input, "p")) {
- print_board(get_board());
+ print_board(get_board(), flipped_last_turn, flipped_last_turn_length);
} else {
sscanf(input, "%d %d", &move.row, &move.col);
}
@@ -82,8 +87,9 @@ struct move prompt_get_move(enum player_color current_player) {
// Returns non-zero number if the move was valid.
// Returns the number of flipped tiles.
-int apply_move(enum player_color **board, enum player_color current_player,
- struct move move) {
+size_t apply_move(enum player_color **board, enum player_color current_player,
+ struct move move, struct move **flipped_spots,
+ size_t *flipped_spots_capacity) {
// The move must be a positive position.
if (move.row < 0 || move.col < 0) {
@@ -107,6 +113,17 @@ int apply_move(enum player_color **board, enum player_color current_player,
done_flipping_up_left = false, done_flipping_up_right = false,
done_flipping_down_left = false, done_flipping_down_right = false;
+#define add_flipped_spot(row_in, col_in) \
+ if (flipped_spots != NULL && flipped_spots_capacity != NULL) { \
+ if (num_flipped == *flipped_spots_capacity) { \
+ *flipped_spots_capacity *= 2; \
+ *flipped_spots = reallocarray(*flipped_spots, *flipped_spots_capacity, \
+ sizeof(struct move)); \
+ } \
+ (*flipped_spots)[num_flipped].row = (row_in); \
+ (*flipped_spots)[num_flipped].col = (col_in); \
+ }
+
for (int i = 1; i < 8; i++) {
if (!done_flipping_up && (move.row - i >= 0) &&
board[move.row - i][move.col] == current_player) {
@@ -122,6 +139,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row - j][move.col] = current_player;
+ add_flipped_spot(move.row - j, move.col);
num_flipped++;
}
}
@@ -143,6 +161,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row + j][move.col] = current_player;
+ add_flipped_spot(move.row + j, move.col);
num_flipped++;
}
}
@@ -164,6 +183,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row][move.col - j] = current_player;
+ add_flipped_spot(move.row, move.col - j);
num_flipped++;
}
}
@@ -185,6 +205,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row][move.col + j] = current_player;
+ add_flipped_spot(move.row, move.col + j);
num_flipped++;
}
}
@@ -206,6 +227,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row - j][move.col - j] = current_player;
+ add_flipped_spot(move.row - j, move.col - j);
num_flipped++;
}
}
@@ -227,6 +249,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row - j][move.col + j] = current_player;
+ add_flipped_spot(move.row - j, move.col + j);
num_flipped++;
}
}
@@ -248,6 +271,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row + j][move.col - j] = current_player;
+ add_flipped_spot(move.row + j, move.col - j);
num_flipped++;
}
}
@@ -269,6 +293,7 @@ int apply_move(enum player_color **board, enum player_color current_player,
if (flippable) {
for (int j = 0; j < i; j++) {
board[move.row + j][move.col + j] = current_player;
+ add_flipped_spot(move.row + j, move.col + j);
num_flipped++;
}
}
@@ -278,6 +303,8 @@ int apply_move(enum player_color **board, enum player_color current_player,
}
}
+#undef add_flipped_spot
+
return num_flipped;
}
@@ -294,7 +321,7 @@ SCM scm_apply_move(SCM scm_move, SCM scm_board, SCM scm_player) {
SCM res_board;
- if (apply_move(board, player, move)) {
+ if (apply_move(board, player, move, NULL, NULL)) {
res_board = scm_board_from_c_board(board);
} else {
res_board = SCM_EOL;
@@ -314,7 +341,7 @@ SCM scm_get_num_flipped_by_move(SCM scm_move, SCM scm_board, SCM scm_player) {
enum player_color player = SCM_UNBNDP(scm_player)
? get_current_player()
: scm_player_to_c_player(scm_player);
- SCM res_num = scm_from_int(apply_move(board, player, move));
+ SCM res_num = scm_from_int(apply_move(board, player, move, NULL, NULL));
free_board(board);
return res_num;
@@ -409,7 +436,7 @@ bool is_valid_move(enum player_color **board,
// necessarily mutate the board yet though.
enum player_color **b = copy_board(board);
// Apply the move to the copy of the board.
- bool res = apply_move(b, current_player, move);
+ bool res = apply_move(b, current_player, move, NULL, NULL);
free_board(b);