X-Git-Url: https://git.cworth.org/git?p=loudgame;a=blobdiff_plain;f=loa-board.c;h=21f4302ffaf676283c0e7b1495f5839f191d0194;hp=8ea6f99d36bb45ad758011bee975ef57faf3c86a;hb=88c5b7fb802cd1eab050dc67289d86dcb37dec6c;hpb=b61845704f880755cbfc2574ac1b3eca8d237f20 diff --git a/loa-board.c b/loa-board.c index 8ea6f99..21f4302 100644 --- a/loa-board.c +++ b/loa-board.c @@ -17,14 +17,93 @@ * Author: Carl Worth */ +#include #include #include #include +#include +#include #include #include "loa-board.h" +static loa_bool_t +loa_move_is_valid (const loa_move_t *move) +{ + return (move->x1 >= 0 && move->x1 < LOA_BOARD_SIZE && + move->y1 >= 0 && move->y1 < LOA_BOARD_SIZE && + move->x2 >= 0 && move->x2 < LOA_BOARD_SIZE && + move->y2 >= 0 && move->y2 < LOA_BOARD_SIZE); +} + +const char * +loa_move_to_string (const loa_move_t *move) +{ +#define LOA_MOVE_STRING_SIZE 6 + static char move_string[LOA_MOVE_STRING_SIZE]; + + if (! loa_move_is_valid (move)) { + strcpy (move_string, "***"); + return move_string; + } + + snprintf (move_string, LOA_MOVE_STRING_SIZE, + "%c%d%c%c%d", + 'a' + move->x1, LOA_BOARD_SIZE - move->y1, + move->is_capture ? 'x' : '-', + 'a' + move->x2, LOA_BOARD_SIZE - move->y2); + + return move_string; +} + +loa_bool_t +loa_move_init_from_string (loa_move_t *move, const char *string) +{ + char xc1, xc2, sep; + int x1, y1, x2, y2; + int matched; + + /* Avoid returning uninitialized data on error. */ + move->x1 = 0; + move->y1 = 0; + move->x2 = 0; + move->y2 = 0; + move->is_capture = 0; + + matched = sscanf (string, "%c%d%c%c%d", &xc1, &y1, &sep, &xc2, &y2); + if (matched != 5) + return FALSE; + + x1 = tolower (xc1) - 'a'; + x2 = tolower (xc2) - 'a'; + y1 = LOA_BOARD_SIZE - y1; + y2 = LOA_BOARD_SIZE - y2; + + if (x1 < 0 || x1 >= LOA_BOARD_SIZE || + y1 < 0 || y1 >= LOA_BOARD_SIZE || + x2 < 0 || x2 >= LOA_BOARD_SIZE || + y2 < 0 || y2 >= LOA_BOARD_SIZE) + { + return FALSE; + } + + if (sep != '-' && sep != 'x' && sep != 'X') + return FALSE; + + move->x1 = x1; + move->y1 = y1; + move->x2 = x2; + move->y2 = y2; + + if (sep == 'x' || sep == 'X') + move->is_capture = TRUE; + else + move->is_capture = FALSE; + + return TRUE; +} + /* Given an (x,y) position on the board, return the index of the array * used to count pieces in diagonal rows running from upper-left to * lower-right, (like a grave accent: à or like a backslash: \). @@ -89,6 +168,22 @@ loa_board_remove_piece (loa_board_t *board, int x, int y) void loa_board_init (loa_board_t *board) +{ + board->moves = NULL; + board->moves_size = 0; + + loa_board_reset (board); +} + +void +loa_board_fini (loa_board_t *board) +{ + if (board->moves) + free (board->moves); +} + +void +loa_board_reset (loa_board_t *board) { int i, x, y; @@ -116,6 +211,9 @@ loa_board_init (loa_board_t *board) loa_board_add_piece (board, LOA_BOARD_SIZE - 1, i, LOA_CELL_WHITE); } + /* Leave board->moves and board->moves_size as allocated */ + board->num_moves = 0; + board->player = LOA_PLAYER_BLACK; } @@ -177,22 +275,25 @@ loa_board_is_won (loa_board_t *board, int x, int y) } static loa_bool_t -loa_board_move_legal (loa_board_t *board, - int x1, int y1, - int x2, int y2, - char **error) +loa_board_move_legal (loa_board_t *board, + const loa_move_t *move, + char **error) { int x, y; + int x1, y1, x2, y2; int dx, dy; int step_x, step_y; - if (x1 < 0 || y1 < 0 || x1 >= LOA_BOARD_SIZE || y1 >= LOA_BOARD_SIZE || - x2 < 0 || y2 < 0 || x2 >= LOA_BOARD_SIZE || y2 >= LOA_BOARD_SIZE) + if (! loa_move_is_valid (move)) { *error = "Invalid coordinates (not on board)"; return FALSE; } + x1 = move->x1; + y1 = move->y1; + x2 = move->x2; + y2 = move->y2; if (board->cells[x1][y1] == LOA_CELL_EMPTY) { *error = "There is no piece there to move"; @@ -285,6 +386,31 @@ loa_board_pass (loa_board_t *board) return TRUE; } +/* Once the move is validated and executed, append it to the moves + * array that stores the move history. */ +static void +loa_board_add_move_to_history (loa_board_t *board, + const loa_move_t *move) +{ + board->num_moves++; + + if (board->num_moves > board->moves_size) { + if (board->moves_size) + board->moves_size *= 2; + else + board->moves_size = 20; + + board->moves = realloc (board->moves, + board->moves_size * sizeof (loa_move_t)); + if (board->moves == NULL) { + fprintf (stderr, "Out of memory.\n"); + exit (1); + } + } + + board->moves[board->num_moves - 1] = *move; +} + int loa_board_move (loa_board_t *board, int x1, int y1, @@ -292,13 +418,30 @@ loa_board_move (loa_board_t *board, char **error) { loa_cell_t cell; + loa_move_t move; - if (! loa_board_move_legal (board, x1, y1, x2, y2, error)) + move.x1 = x1; + move.y1 = y1; + move.x2 = x2; + move.y2 = y2; + + if (! loa_board_move_legal (board, &move, error)) return FALSE; cell = loa_board_remove_piece (board, x1, y1); - loa_board_remove_piece (board, x2, y2); - loa_board_add_piece (board, x2, y2, cell); + assert (cell == board->player); + + cell = loa_board_remove_piece (board, x2, y2); + if (cell == LOA_CELL_EMPTY) { + move.is_capture = FALSE; + } else { + assert (cell != board->player); + move.is_capture = TRUE; + } + + loa_board_add_piece (board, x2, y2, board->player); + + loa_board_add_move_to_history (board, &move); loa_board_next_player (board);