From a5706c0be5778b911b061deca501271fc2bf2c07 Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Fri, 21 Jan 2022 17:49:09 -0500 Subject: 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. --- cmd/main.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- include/othello.h | 7 +++---- src/board.c | 11 +++-------- src/game_loop.c | 5 +++-- 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 specify a file to use for player one strategy\n" - " -2 --player-two specify a file to use for player two strategy\n"; + " -2 --player-two 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); } -- cgit v1.2.3