diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | cmd/main.c | 43 | ||||
-rw-r--r-- | include/othello.h | 10 | ||||
-rw-r--r-- | include/othello_move.h | 2 | ||||
-rw-r--r-- | src/game_loop.c | 62 | ||||
-rw-r--r-- | src/move.c | 47 |
6 files changed, 101 insertions, 66 deletions
@@ -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) @@ -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(); } @@ -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; } - - |