summaryrefslogtreecommitdiff
path: root/src/move.c
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2022-01-21 17:20:17 -0500
committerRobby Zambito <contact@robbyzambito.me>2022-01-21 17:20:17 -0500
commitf1a4b5757f0d20739270b22726ebf8442b13cb50 (patch)
tree93e170ddebc79cf5a41777fc040797bc6dfa5d85 /src/move.c
parent3a85be307b6240525f032b9fad5114bdf172bdc1 (diff)
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.
Diffstat (limited to 'src/move.c')
-rw-r--r--src/move.c134
1 files changed, 60 insertions, 74 deletions
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 <readline/readline.h>
#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);