summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2022-01-17 17:58:28 -0500
committerRobby Zambito <contact@robbyzambito.me>2022-01-17 17:58:28 -0500
commit59627145631f254191ce1b9de561c8ba0ddc889e (patch)
treefe6c45083da7ce34bb93f67fe22bf6877c47b918
parent6a9badff9bfbbdd7f54f018d3117c1778ecaa74e (diff)
Successfully read a move from scheme
Also was able to print the current board from scheme, so we should be able to do basic analysis at least. Should add more primitives for use from scheme.
-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;
}
-
-