From 74df2492e8c32df37d886dec4baf9344dc6b8cff Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 5 Mar 2009 08:50:59 -0800 Subject: [PATCH] Enforce legal moves All the checks for legal moves are now enforced, (including not even selecting a piece if it is surrounded). Basically all that's missing now is elimination of disconnected pieces, (and the ability to pass when there is no available move). --- dvonn-board.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++--- dvonn-board.h | 13 +++++++++ dvonn.c | 18 ++++++++----- 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/dvonn-board.c b/dvonn-board.c index 4d09e13..b6b36e5 100644 --- a/dvonn-board.c +++ b/dvonn-board.c @@ -82,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 || @@ -97,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; } diff --git a/dvonn-board.h b/dvonn-board.h index 2971a27..66464d8 100644 --- a/dvonn-board.h +++ b/dvonn-board.h @@ -88,4 +88,17 @@ dvonn_board_move (dvonn_board_t *board, int x2, int y2, char **error); +/* Is the cell at (x,y) occupied by a piece. Returns FALSE for all + * out-of-bounds coordinates. */ +dvonn_bool_t +dvonn_board_cell_occupied (dvonn_board_t *board, + int x, int y); + +/* Is the cell at (x,y) surrounded by other pieces, (such that it is + * not legal for a piece at (x,y) to move. */ +dvonn_bool_t +dvonn_board_cell_surrounded (dvonn_board_t *board, + int x, int y); + + #endif diff --git a/dvonn.c b/dvonn.c index 806a8e6..8ac72b1 100644 --- a/dvonn.c +++ b/dvonn.c @@ -157,6 +157,10 @@ on_button_press_event (GtkWidget *widget, int x, y; char *error; + /* Ignore double and triple clicks. */ + if (event->type >= GDK_2BUTTON_PRESS) + return TRUE; + x = event->x; y = event->y; layout_device_to_board (layout, &x, &y); @@ -185,12 +189,14 @@ on_button_press_event (GtkWidget *widget, } if (! game->has_selected) { - if (game->board.cells[x][y].type == game->board.player) { - game->has_selected = TRUE; - game->selected_x = x; - game->selected_y = y; - dvonn_game_update_windows (game); - } + if (game->board.cells[x][y].type == game->board.player && + ! dvonn_board_cell_surrounded (&game->board, x, y)) + { + game->has_selected = TRUE; + game->selected_x = x; + game->selected_y = y; + dvonn_game_update_windows (game); + } return TRUE; } -- 2.43.0