X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=dvonn-board.c;h=5b7c106c311909b30a47d96dc7ff3c6e7ecaf418;hb=491f9bdf58e9ad5b23858e3f780a506c45e867b2;hp=795ff5531d6ed2726e4b24907ccbb5ecbc5fe96f;hpb=0eff3c58b93ea73e7f1aa866f6e317714479dd6e;p=dvonn diff --git a/dvonn-board.c b/dvonn-board.c index 795ff55..5b7c106 100644 --- a/dvonn-board.c +++ b/dvonn-board.c @@ -63,6 +63,7 @@ dvonn_board_init (dvonn_board_t *board) for (y = 0; y < DVONN_BOARD_Y_SIZE; y++) { board->cells[x][y].type = DVONN_CELL_EMPTY; board->cells[x][y].height = 0; + board->cells[x][y].contains_red = FALSE; } } @@ -81,12 +82,50 @@ dvonn_board_init (dvonn_board_t *board) board->moves = 0; } +dvonn_bool_t +dvonn_board_cell_occupied (dvonn_board_t *board, + int x, int y) +{ + if (x < 0 || x >= DVONN_BOARD_X_SIZE || + y < 0 || y >= DVONN_BOARD_Y_SIZE) + { + return FALSE; + } + + if (board->cells[x][y].type == DVONN_CELL_INVALID || + board->cells[x][y].type == DVONN_CELL_EMPTY) + { + return FALSE; + } + + return TRUE; +} + +dvonn_bool_t +dvonn_board_cell_surrounded (dvonn_board_t *board, + int x, int y) +{ + int surround_count; + + surround_count = + dvonn_board_cell_occupied (board, x - 1, y) + + dvonn_board_cell_occupied (board, x + 1, y) + + dvonn_board_cell_occupied (board, x, y - 1) + + dvonn_board_cell_occupied (board, x, y + 1) + + dvonn_board_cell_occupied (board, x + 1, y - 1) + + dvonn_board_cell_occupied (board, x - 1, y + 1); + + return (surround_count == 6); +} + static dvonn_bool_t dvonn_board_move_legal (dvonn_board_t *board, int x1, int y1, int x2, int y2, char **error) { + int distance; + if (x1 < 0 || x1 >= DVONN_BOARD_X_SIZE || y1 < 0 || y1 >= DVONN_BOARD_Y_SIZE || x2 < 0 || x2 >= DVONN_BOARD_X_SIZE || @@ -96,22 +135,50 @@ dvonn_board_move_legal (dvonn_board_t *board, return FALSE; } - if (board->cells[x1][y1].type == DVONN_CELL_INVALID) { + if (board->cells[x1][y1].type == DVONN_CELL_INVALID || + board->cells[x2][y2].type == DVONN_CELL_INVALID) + { *error = "Not a valid board space"; return FALSE; } if (board->cells[x1][y1].type == DVONN_CELL_EMPTY) { - *error = "There is no piece there to move"; + *error = "There are no pieces there to move"; + return FALSE; + } + + if (dvonn_board_cell_surrounded (board, x1, y1)) { + *error = "You cannot move a piece that is surrounded"; return FALSE; } if (board->cells[x1][y1].type != board->player) { - *error = "You cannot move your opponent's piece"; + *error = "You cannot move your opponent's stack"; return FALSE; } - /* XXX: Need to code up DVONN-legal move calculation here. */ + if (board->cells[x2][y2].type == DVONN_CELL_EMPTY) { + *error = "You cannot move to an empty space"; + return FALSE; + } + + /* Move must be in a straight line, which in our array is + * horizontal, vertical, or one of the diagonals. */ + if (x2 == x1) + distance = abs (y2 - y1); + else if (y2 == y1) + distance = abs (x2 - x1); + else if ((x2 - x1) == - (y2 - y1)) + distance = abs (x2 - x1); + else { + *error = "Move is not in a straight line"; + return FALSE; + } + + if (distance != board->cells[x1][y1].height) { + *error = "Move distance is not the same as stack height"; + return FALSE; + } return TRUE; } @@ -125,6 +192,17 @@ dvonn_board_next_player (dvonn_board_t *board) board->player = DVONN_PLAYER_BLACK; } +int +dvonn_board_pass (dvonn_board_t *board) +{ + /* XXX: Should check here and only allow a pass if there are + * no legal moves. */ + + dvonn_board_next_player (board); + + return TRUE; +} + int dvonn_board_place (dvonn_board_t *board, int x, int y, @@ -140,12 +218,16 @@ dvonn_board_place (dvonn_board_t *board, return FALSE; } - if (board->moves < 3) + if (board->moves < 3) { board->cells[x][y].type = DVONN_CELL_RED; - else if (board->moves % 2) + board->cells[x][y].contains_red = TRUE; + } else if (board->moves % 2) { board->cells[x][y].type = DVONN_CELL_BLACK; - else + } else { board->cells[x][y].type = DVONN_CELL_WHITE; + } + + board->cells[x][y].height = 1; board->moves++; @@ -157,6 +239,49 @@ dvonn_board_place (dvonn_board_t *board, return TRUE; } +static void +fill_living(dvonn_board_t *board, + int living[DVONN_BOARD_X_SIZE][DVONN_BOARD_Y_SIZE], + int x, int y) +{ + if (dvonn_board_cell_occupied (board, x, y) && ! living[x][y]) + { + living[x][y] = 1; + + fill_living (board, living, x - 1, y); + fill_living (board, living, x + 1, y); + fill_living (board, living, x, y - 1); + fill_living (board, living, x, y + 1); + fill_living (board, living, x + 1, y - 1); + fill_living (board, living, x - 1, y + 1); + } +} + +static void +eliminate_disconnected_stacks (dvonn_board_t *board) +{ + int x, y; + int living[DVONN_BOARD_X_SIZE][DVONN_BOARD_Y_SIZE]; + + for (x = 0; x < DVONN_BOARD_X_SIZE; x++) + for (y = 0; y < DVONN_BOARD_Y_SIZE; y++) + living[x][y] = 0; + + for (x = 0; x < DVONN_BOARD_X_SIZE; x++) + for (y = 0; y < DVONN_BOARD_Y_SIZE; y++) + if (board->cells[x][y].contains_red) + fill_living (board, living, x, y); + + for (x = 0; x < DVONN_BOARD_X_SIZE; x++) + for (y = 0; y < DVONN_BOARD_Y_SIZE; y++) + if (dvonn_board_cell_occupied (board, x, y) && + ! living[x][y]) + { + board->cells[x][y].type = DVONN_CELL_EMPTY; + board->cells[x][y].height = 0; + } +} + int dvonn_board_move (dvonn_board_t *board, int x1, int y1, @@ -171,7 +296,15 @@ dvonn_board_move (dvonn_board_t *board, if (! dvonn_board_move_legal (board, x1, y1, x2, y2, error)) return FALSE; - /* XXX: Need to execute the move here. */ + board->cells[x2][y2].height += board->cells[x1][y1].height; + board->cells[x2][y2].type = board->cells[x1][y1].type; + board->cells[x2][y2].contains_red |= board->cells[x1][y1].contains_red; + + board->cells[x1][y1].type = DVONN_CELL_EMPTY; + board->cells[x1][y1].height = 0; + board->cells[x1][y1].contains_red = FALSE; + + eliminate_disconnected_stacks (board); dvonn_board_next_player (board);