summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--cmd/main.c43
-rw-r--r--include/othello.h10
-rw-r--r--include/othello_move.h2
-rw-r--r--src/game_loop.c62
-rw-r--r--src/move.c47
6 files changed, 101 insertions, 66 deletions
diff --git a/Makefile b/Makefile
index 332c8b8..34d4615 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,8 @@ build: output_dir
gcc -Ofast $(LIBRARIES) $(SOURCES) $(OUTPUT:PROG=othello)
debug: output_dir
- gcc -std=c11 -g -Wall -Wextra -Wpedantic -Werror $(LIBRARIES) $(SOURCES) $(OUTPUT:PROG=othello)
+ #gcc -std=c11 -g -Wall -Wextra -Wpedantic -Werror $(LIBRARIES) $(SOURCES) $(OUTPUT:PROG=othello)
+ gcc -std=c11 -g $(LIBRARIES) $(SOURCES) $(OUTPUT:PROG=othello)
output_dir:
mkdir -p $(OUTPUT_DIR)
diff --git a/cmd/main.c b/cmd/main.c
index c85704a..d87be49 100644
--- a/cmd/main.c
+++ b/cmd/main.c
@@ -18,17 +18,20 @@
#define _GNU_SOURCE
-#include <getopt.h>
#include <errno.h>
+#include <getopt.h>
#include <libguile.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "othello.h"
int main(int argc, char **argv) {
+ int exit_status = EXIT_SUCCESS;
+
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"player-one", required_argument, NULL, '1'},
@@ -40,8 +43,8 @@ int main(int argc, char **argv) {
" -1 --player-one <file> specify a file to use for player one strategy\n"
" -2 --player-two <file> specify a file to use for player two strategy\n";
- FILE *player_one_strategy = NULL;
- FILE *player_two_strategy = NULL;
+ char *player_one_strategy_path = NULL;
+ char *player_two_strategy_path = NULL;
int c;
while (1) {
@@ -56,31 +59,31 @@ int main(int argc, char **argv) {
printf("%s", usage);
exit(EXIT_SUCCESS);
case '1':
- /*char *player_one_strategy_path = strdup(optarg);*/
- if (player_one_strategy != NULL) {
- fclose(player_one_strategy);
- }
- player_one_strategy = fopen(optarg, "r");
- if (errno != 0) {
- perror("Could not open player 1 strategy");
+ player_one_strategy_path = strdup(optarg);
+ if (access(player_one_strategy_path, F_OK) == -1) {
+ fprintf(stderr, "Could not access player 1 strategy\n");
+ exit_status = EXIT_FAILURE;
}
- /*free(player_one_strategy_path);*/
break;
case '2':
- if (player_two_strategy != NULL) {
- fclose(player_two_strategy);
+ player_two_strategy_path = strdup(optarg);
+ if (access(player_two_strategy_path, F_OK) == -1) {
+ fprintf(stderr, "Could not access player 2 strategy\n");
+ exit_status = EXIT_FAILURE;
}
- player_two_strategy = fopen(optarg, "r");
- if (errno != 0) {
- perror("Could not open player 2 strategy");
- }
- /*char *player_two_strategy_path = strdup(optarg);*/
- /*free(player_two_strategy_path);*/
break;
}
}
- enum player_color winner = game_loop(player_one_strategy, player_two_strategy);
+ // Couldn't open one or more of the player strategies, bail out.
+ if (exit_status == EXIT_FAILURE) {
+ exit(EXIT_FAILURE);
+ }
+
+ enum player_color winner =
+ game_loop(player_one_strategy_path, player_two_strategy_path);
+ free(player_one_strategy_path);
+ free(player_two_strategy_path);
switch (winner) {
case WHITE:
diff --git a/include/othello.h b/include/othello.h
index de4f846..14c402b 100644
--- a/include/othello.h
+++ b/include/othello.h
@@ -41,9 +41,15 @@ extern struct move (*player_two_get_move)(void);
// Set a board to a new game state.
void initialize_board(void);
+// Copy the specified board. It must be freed by the caller.
+enum player_color **copy_board(enum player_color **board);
+
+// Free the specified board.
+enum player_color **free_board(enum player_color **board);
+
// Plays a game to completion, starting with board.
-enum player_color game_loop(FILE *player_one_strategy,
- FILE *player_two_strategy);
+enum player_color game_loop(char *player_one_strategy,
+ char *player_two_strategy);
// Prints the current state of the board, including coordinates in the margins.
void print_board(void);
diff --git a/include/othello_move.h b/include/othello_move.h
index 377a27f..0c3716e 100644
--- a/include/othello_move.h
+++ b/include/othello_move.h
@@ -23,7 +23,7 @@
#include "othello.h"
struct move prompt_get_move(enum player_color current_player);
-struct move get_scm_move(FILE *strategy);
+struct move get_scm_move(char *strategy_path);
// True if move is valid for current_player.
// Otherwise false.
diff --git a/src/game_loop.c b/src/game_loop.c
index 26cb988..67c9ea0 100644
--- a/src/game_loop.c
+++ b/src/game_loop.c
@@ -40,46 +40,46 @@ struct move (*player_one_get_move)();
struct move (*player_two_get_move)();
static struct move current_player_move(enum player_color current_player,
- FILE *player_one_strategy,
- FILE *player_two_strategy) {
- struct move move = {-1, -1};
-
- if ((current_player == WHITE && player_one_strategy == NULL) ||
- (current_player == BLACK && player_two_strategy == NULL)) {
- move = prompt_get_move(current_player);
- } else if (current_player == WHITE) {
- move = get_scm_move(player_one_strategy);
- } else if (current_player == BLACK) {
- move = get_scm_move(player_two_strategy);
- }
-
- return move;
+ char *player_one_strategy_path,
+ char *player_two_strategy_path) {
+ 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);
+ } else if (current_player == WHITE) {
+ move = get_scm_move(player_one_strategy_path);
+ } else if (current_player == BLACK) {
+ move = get_scm_move(player_two_strategy_path);
+ }
+
+ return move;
}
-enum player_color game_loop(FILE *player_one_strategy,
- FILE *player_two_strategy) {
- initialize_board();
+enum player_color game_loop(char *player_one_strategy_path,
+ char *player_two_strategy_path) {
+ initialize_board();
- if (player_one_strategy == NULL || player_two_strategy == NULL) {
- using_history();
- }
+ if (player_one_strategy_path == NULL || player_two_strategy_path == NULL) {
+ using_history();
+ }
- current_player = WHITE;
+ current_player = WHITE;
#define other_player (current_player == WHITE ? BLACK : WHITE)
- while (has_valid_moves(current_player)) {
- struct move move = current_player_move(current_player, player_one_strategy,
- player_two_strategy);
- if (apply_move(get_board(), current_player, move)) {
- current_player = other_player;
- }
+ while (has_valid_moves(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 = other_player;
}
+ }
#undef other_player
- if (player_one_strategy == NULL || player_two_strategy == NULL) {
- rl_clear_history();
- }
+ if (player_one_strategy_path == NULL || player_two_strategy_path == NULL) {
+ rl_clear_history();
+ }
- return get_winner();
+ return get_winner();
}
diff --git a/src/move.c b/src/move.c
index 968dcfa..60cf58b 100644
--- a/src/move.c
+++ b/src/move.c
@@ -53,11 +53,6 @@ static char *prompt_player(enum player_color current_player) {
}
}
-/*static void inner_main(void *closure, int argc, char **argv) {*/
- /*(void)closure;*/
- /*scm_shell(argc, argv);*/
-/*}*/
-
struct move prompt_get_move(enum player_color current_player) {
// Initialize move to an invalid move.
struct move move = {-1, -1};
@@ -72,7 +67,7 @@ struct move prompt_get_move(enum player_color current_player) {
print_help();
} else if (STREQ(input, "p")) {
print_board();
- /*} else if (STREQ(input, "g")) {*/
+ /*} else if (STREQ(input, "g")) {*/
/*int argc = 1;*/
/*char **argv = calloc(1, sizeof(char *));*/
/*argv[0] = "othello";*/
@@ -95,7 +90,8 @@ struct move prompt_get_move(enum player_color current_player) {
}
/* Returns true if the move was valid */
-bool apply_move(enum player_color **board, enum player_color current_player, struct move move) {
+bool apply_move(enum player_color **board, enum player_color current_player,
+ struct move move) {
// The move must be a positive position.
if (move.row < 0 || move.col < 0) {
@@ -179,11 +175,40 @@ bool apply_move(enum player_color **board, enum player_color current_player, str
return flipped_up || flipped_down || flipped_left || flipped_right;
}
-struct move get_scm_move(FILE *strategy) {
+// Return the current board as a list of lists
+static SCM scm_get_board(void) {
+ enum player_color **board = get_board();
+ // 2D list of empty spaces
+ SCM scm_board =
+ scm_make_list(scm_from_int(8), scm_make_list(scm_from_int(0), NULL));
+ for (int i = 0; i < 8; i++) {
+ for (int j = 7; j >= 0; j--) {
+ if (board[i][j] == WHITE) {
+ scm_list_set_x(scm_board, scm_from_int(i),
+ scm_cons(scm_c_eval_string("'w"),
+ scm_list_ref(scm_board, scm_from_int(i))));
+ } else if (board[i][j] == BLACK) {
+ scm_list_set_x(scm_board, scm_from_int(i),
+ scm_cons(scm_c_eval_string("'b"),
+ scm_list_ref(scm_board, scm_from_int(i))));
+ } else {
+ scm_list_set_x(scm_board, scm_from_int(i),
+ scm_cons(scm_c_eval_string("'e"),
+ scm_list_ref(scm_board, scm_from_int(i))));
+ }
+ }
+ }
+ return scm_board;
+}
+
+struct move get_scm_move(char *strategy_path) {
// Initialize move to an invalid move.
struct move move = {-1, -1};
+ scm_init_guile();
+ scm_c_define_gsubr("get-board", 0, 0, 0, scm_get_board);
+
+ SCM scm_move = scm_c_primitive_load(strategy_path);
+ move.row = scm_to_int(scm_car(scm_move));
+ move.col = scm_to_int(scm_cdr(scm_move));
return move;
- (void)strategy;
}
-
-