From f1a4b5757f0d20739270b22726ebf8442b13cb50 Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Fri, 21 Jan 2022 17:20:17 -0500 Subject: Fleshed out Scheme primitives * Moved board specific functions from othello.h to new othello_board.h * Removed unused function pointer for player moves * Added prototypes in headers for SCM functions, including scm_get_current_player, * Made get_winner accept a board and current player. This is useful for predictions to see if some move would make the other player a winner. * get_winner also writes the players scores to provided pointers. --- src/move.c | 134 +++++++++++++++++++++++++++---------------------------------- 1 file changed, 60 insertions(+), 74 deletions(-) (limited to 'src/move.c') diff --git a/src/move.c b/src/move.c index 8828ef0..d2a05dd 100644 --- a/src/move.c +++ b/src/move.c @@ -25,6 +25,7 @@ #include #include "othello.h" +#include "othello_board.h" #include "othello_move.h" #define STREQ(a, b) (strcmp(a, b) == 0) @@ -175,104 +176,87 @@ bool apply_move(enum player_color **board, enum player_color current_player, return flipped_up || flipped_down || flipped_left || flipped_right; } -// 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_from_utf8_symbol("white"), - 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_from_utf8_symbol("black"), - scm_list_ref(scm_board, scm_from_int(i)))); - } else { - scm_list_set_x(scm_board, scm_from_int(i), - scm_cons(scm_from_utf8_symbol("empty"), - scm_list_ref(scm_board, scm_from_int(i)))); - } - } +SCM scm_apply_move(SCM scm_move, SCM scm_board, SCM scm_player) { + struct move move = scm_move_to_c_move(scm_move); + + enum player_color **board; + if (scm_is_null(scm_board)) { + board = copy_board(get_board()); + } else { + board = scm_board_to_c_board(scm_board); + } + + enum player_color player; + if (scm_is_null(scm_player)) { + player = get_current_player(); + } else { + player = scm_player_to_c_player(scm_player); } - return scm_board; + + SCM res_board; + + if (apply_move(board, player, move)) { + res_board = scm_board_from_c_board(board); + } else { + res_board = SCM_EOL; + } + + free_board(board); + return res_board; } -static struct move scm_move_to_c_move(SCM scm_move) { +struct move scm_move_to_c_move(SCM scm_move) { struct move move = {-1, -1}; move.row = scm_to_int(scm_car(scm_move)); move.col = scm_to_int(scm_cdr(scm_move)); return move; } -static SCM scm_current_player(void) { - switch (get_current_player()) { - case WHITE: - return scm_from_utf8_symbol("white"); - case BLACK: - return scm_from_utf8_symbol("black"); - default: - return scm_from_utf8_symbol("empty"); - } +SCM scm_move_from_c_move(struct move move) { + return scm_cons(scm_from_int(move.row), scm_from_int(move.col)); } -static SCM scm_is_valid_move(SCM scm_board, SCM scm_player, SCM scm_move) { - enum player_color **board = calloc(8, sizeof(enum player_color *)); - for (int i = 0; i < 8; i++) { - board[i] = calloc(8, sizeof(enum player_color)); - for (int j = 0; j < 8; j++) { - if (scm_is_true( - scm_eq_p(scm_list_ref(scm_list_ref(scm_board, scm_from_int(i)), - scm_from_int(j)), - scm_from_utf8_symbol("white")))) { - board[i][j] = WHITE; - } else if (scm_is_true(scm_eq_p( - scm_list_ref(scm_list_ref(scm_board, scm_from_int(i)), - scm_from_int(j)), - scm_from_utf8_symbol("black")))) { - board[i][j] = BLACK; - } else { - board[i][j] = EMPTY; - } - } - } +SCM scm_is_valid_move(SCM scm_move, SCM scm_board, SCM scm_player) { + enum player_color **board = + SCM_UNBNDP(scm_board) ? get_board() : scm_board_to_c_board(scm_board); - enum player_color current_player = BLACK; + enum player_color current_player = SCM_UNBNDP(scm_player) + ? get_current_player() + : scm_player_to_c_player(scm_player); struct move move = scm_move_to_c_move(scm_move); - return scm_from_bool(is_valid_move(board, current_player, move)); -} + SCM is_valid = scm_from_bool(is_valid_move(board, current_player, move)); -// Return the list of valid moves on a board for a player -static SCM scm_valid_moves(SCM scm_board, SCM player) { - enum player_color **board = calloc(8, sizeof(enum player_color *)); - for (int i = 0; i < 8; i++) { - board[i] = calloc(8, sizeof(enum player_color)); + if (!SCM_UNBNDP(scm_board)) { + free_board(board); } - enum player_color current_player = EMPTY; + return is_valid; +} - if (scm_is_true(scm_eq_p(player, scm_from_utf8_symbol("white")))) { - current_player = WHITE; - } else if (scm_is_true(scm_eq_p(player, scm_from_utf8_symbol("black")))) { - current_player = BLACK; - } - current_player = BLACK; +// Return the list of valid moves on a board for a player +SCM scm_valid_moves(SCM scm_board, SCM player) { + enum player_color **board = + SCM_UNBNDP(scm_board) ? get_board() : scm_board_to_c_board(scm_board); - SCM result = scm_make_list(scm_from_int(0), NULL); + enum player_color current_player = SCM_UNBNDP(player) + ? get_current_player() + : scm_player_to_c_player(player); + + SCM result = SCM_EOL; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { struct move move = {i, j}; if (is_valid_move(board, current_player, move)) { - result = scm_cons(scm_cons(scm_from_int(i), scm_from_int(j)), result); + result = scm_cons(scm_move_from_c_move(move), result); } } } - free_board(board); + if (!SCM_UNBNDP(scm_board)) { + free_board(board); + } + return result; } @@ -283,9 +267,11 @@ struct move get_scm_move(char *strategy_path) { // Initialize primitives scm_c_define_gsubr("get-board", 0, 0, 0, scm_get_board); - scm_c_define_gsubr("current-player", 0, 0, 0, scm_current_player); - scm_c_define_gsubr("valid-move?", 3, 0, 0, scm_is_valid_move); - scm_c_define_gsubr("valid-moves", 2, 0, 0, scm_valid_moves); + scm_c_define_gsubr("current-player", 0, 0, 0, scm_get_current_player); + scm_c_define_gsubr("valid-move?", 1, 2, 0, scm_is_valid_move); + scm_c_define_gsubr("valid-moves", 0, 2, 0, scm_valid_moves); + scm_c_define_gsubr("apply-move", 1, 2, 0, scm_apply_move); + scm_c_define_gsubr("get-winner", 2, 0, 0, scm_get_winner); // Read the move from scheme SCM scm_move = scm_c_primitive_load(strategy_path); -- cgit v1.2.3