summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2022-01-21 17:49:09 -0500
committerRobby Zambito <contact@robbyzambito.me>2022-01-21 17:49:09 -0500
commita5706c0be5778b911b061deca501271fc2bf2c07 (patch)
tree1087eb740715e692820ff1e275cf61a7ca1b0ea8
parent199b2ff1b66bf2e12c9bf0b55a895a5555cc52f7 (diff)
Add command line argument to print the final board as a scheme object
This could be useful to create a machine learning AI, which uses the final board for training. Also bubble up the final score and present it at the end of the game.
-rw-r--r--cmd/main.c54
-rw-r--r--include/othello.h7
-rw-r--r--src/board.c11
-rw-r--r--src/game_loop.c5
4 files changed, 48 insertions, 29 deletions
diff --git a/cmd/main.c b/cmd/main.c
index 12d7f3a..5863889 100644
--- a/cmd/main.c
+++ b/cmd/main.c
@@ -37,20 +37,23 @@ int main(int argc, char **argv) {
{"help", no_argument, NULL, 'h'},
{"player-one", required_argument, NULL, '1'},
{"player-two", required_argument, NULL, '2'},
+ {"scm-final-board", no_argument, NULL, 's'},
{0, 0, 0, 0}};
const char *usage =
" -h --help show help output\n"
" -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";
+ " -2 --player-two <file> specify a file to use for player two strategy\n"
+ " -s --scm-final-board print the final board as a Scheme object\n";
char *player_one_strategy_path = NULL;
char *player_two_strategy_path = NULL;
+ bool should_print_as_scm = false;
int c;
while (1) {
int option_index = 0;
- c = getopt_long(argc, argv, "h1:2:", long_options, &option_index);
+ c = getopt_long(argc, argv, "h1:2:s", long_options, &option_index);
if (c == -1) {
break;
}
@@ -73,6 +76,9 @@ int main(int argc, char **argv) {
exit_status = EXIT_FAILURE;
}
break;
+ case 's':
+ should_print_as_scm = true;
+ break;
}
}
@@ -81,24 +87,42 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
+ int white_score, black_score;
enum player_color winner =
- game_loop(player_one_strategy_path, player_two_strategy_path);
+ game_loop(player_one_strategy_path, player_two_strategy_path,
+ &white_score, &black_score);
free(player_one_strategy_path);
free(player_two_strategy_path);
- switch (winner) {
- case WHITE:
- puts("Congratulations for winning player 1!");
- break;
- case BLACK:
- puts("Congratulations for winning player 2!");
- break;
- default:
- puts("The game ended with no winner.");
- }
+ if (should_print_as_scm) {
+ // Make sure guile has been initialized.
+ // It probably has, since it is unlikely that the user would want to
+ // print the final board as a Scheme object if they have no Scheme
+ // players... but it is possible.
+ scm_init_guile();
+
+ scm_c_eval_string("(use-modules (ice-9 pretty-print))"
+ "(pretty-print (get-board))");
+ printf("%d\n", white_score);
+ printf("%d\n", black_score);
+ } else {
+ switch (winner) {
+ case WHITE:
+ puts("Congratulations for winning player 1!");
+ break;
+ case BLACK:
+ puts("Congratulations for winning player 2!");
+ break;
+ default:
+ puts("The game ended with no winner.");
+ }
- puts("Here was the final board:");
- print_board(get_board());
+ puts("Here was the final board:");
+ print_board(get_board());
+
+ printf("Final white score: %d\n", white_score);
+ printf("Final black score: %d\n", black_score);
+ }
return EXIT_SUCCESS;
}
diff --git a/include/othello.h b/include/othello.h
index e46c13e..88b8be2 100644
--- a/include/othello.h
+++ b/include/othello.h
@@ -35,10 +35,10 @@ struct move {
int col;
};
-
// Plays a game to completion, starting with board.
enum player_color game_loop(char *player_one_strategy,
- char *player_two_strategy);
+ char *player_two_strategy, int *white_score,
+ int *black_score);
// Returns the color of the player whose turn it is.
enum player_color get_current_player(void);
@@ -47,7 +47,6 @@ SCM scm_get_current_player(void);
enum player_color scm_player_to_c_player(SCM player);
enum player_color get_winner(enum player_color **board,
- enum player_color current_player,
- int *white_score,
+ enum player_color current_player, int *white_score,
int *black_score);
SCM scm_get_winner(SCM board, SCM current_player);
diff --git a/src/board.c b/src/board.c
index 88c7dff..aec166a 100644
--- a/src/board.c
+++ b/src/board.c
@@ -29,9 +29,7 @@ static enum player_color **board;
enum player_color **get_board() { return board; }
-SCM scm_get_board() {
- return scm_board_from_c_board(board);
-}
+SCM scm_get_board() { return scm_board_from_c_board(board); }
void initialize_board() {
board = calloc(8, sizeof(enum player_color *));
@@ -75,9 +73,7 @@ enum player_color get_winner(enum player_color **board,
*black_score = bs;
}
- return white_score > black_score ? WHITE
- : black_score > white_score ? BLACK
- : EMPTY;
+ return ws > bs ? WHITE : bs > ws ? BLACK : EMPTY;
}
SCM scm_get_winner(SCM scm_board, SCM scm_current_player) {
@@ -112,8 +108,7 @@ void free_board(enum player_color **board) {
SCM scm_board_from_c_board(enum player_color **board) {
// 2D list of empty rows
- SCM scm_board =
- scm_make_list(scm_from_int(8), SCM_EOL);
+ SCM scm_board = scm_make_list(scm_from_int(8), SCM_EOL);
for (int i = 0; i < 8; i++) {
// cons up each row.
diff --git a/src/game_loop.c b/src/game_loop.c
index f52bdb7..2c70ce2 100644
--- a/src/game_loop.c
+++ b/src/game_loop.c
@@ -76,7 +76,8 @@ static struct move current_player_move(enum player_color current_player,
}
enum player_color game_loop(char *player_one_strategy_path,
- char *player_two_strategy_path) {
+ char *player_two_strategy_path, int *white_score,
+ int *black_score) {
initialize_board();
if (player_one_strategy_path == NULL || player_two_strategy_path == NULL) {
@@ -100,5 +101,5 @@ enum player_color game_loop(char *player_one_strategy_path,
rl_clear_history();
}
- return get_winner(get_board(), current_player, NULL, NULL);
+ return get_winner(get_board(), current_player, white_score, black_score);
}