From 0eff3c58b93ea73e7f1aa866f6e317714479dd6e Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 5 Mar 2009 01:03:05 -0800 Subject: [PATCH] Implement placement phase of game It's getting *close* to playable now. We still need visual indications for the following: stack height, red piece in stack, selected stack, and most recently moved stack. We also need logic for legal moves as well as for removing disconnected pieces after a move. But that's not really that much code. --- dvonn-board.c | 39 +++++++++++++++++++++++++++++++++++++++ dvonn-board.h | 19 ++++++++++++++++++- dvonn.c | 39 ++++++++++++++++++++++++++------------- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/dvonn-board.c b/dvonn-board.c index 35789e7..795ff55 100644 --- a/dvonn-board.c +++ b/dvonn-board.c @@ -76,7 +76,9 @@ dvonn_board_init (dvonn_board_t *board) } } + board->phase = DVONN_PHASE_PLACEMENT; board->player = DVONN_PLAYER_WHITE; + board->moves = 0; } static dvonn_bool_t @@ -123,12 +125,49 @@ dvonn_board_next_player (dvonn_board_t *board) board->player = DVONN_PLAYER_BLACK; } +int +dvonn_board_place (dvonn_board_t *board, + int x, int y, + char **error) +{ + if (board->phase != DVONN_PHASE_PLACEMENT) { + *error = "Cannot place outside of placement phase"; + return FALSE; + } + + if (board->cells[x][y].type != DVONN_CELL_EMPTY) { + *error = "Cannot place on an occupied space"; + return FALSE; + } + + if (board->moves < 3) + board->cells[x][y].type = DVONN_CELL_RED; + else if (board->moves % 2) + board->cells[x][y].type = DVONN_CELL_BLACK; + else + board->cells[x][y].type = DVONN_CELL_WHITE; + + board->moves++; + + if (board->moves == 49) { + board->phase = DVONN_PHASE_MOVEMENT; + board->moves = 0; + } + + return TRUE; +} + int dvonn_board_move (dvonn_board_t *board, int x1, int y1, int x2, int y2, char **error) { + if (board->phase != DVONN_PHASE_MOVEMENT) { + *error = "Cannot move outside of placement phase"; + return FALSE; + } + if (! dvonn_board_move_legal (board, x1, y1, x2, y2, error)) return FALSE; diff --git a/dvonn-board.h b/dvonn-board.h index c1c8270..b0ee8cc 100644 --- a/dvonn-board.h +++ b/dvonn-board.h @@ -37,6 +37,7 @@ typedef enum { typedef enum { DVONN_CELL_BLACK = DVONN_PLAYER_BLACK, DVONN_CELL_WHITE = DVONN_PLAYER_WHITE, + DVONN_CELL_RED, DVONN_CELL_EMPTY, DVONN_CELL_INVALID } dvonn_cell_type_t; @@ -49,16 +50,32 @@ typedef struct { #define DVONN_BOARD_X_SIZE 11 #define DVONN_BOARD_Y_SIZE 5 +typedef enum { + DVONN_PHASE_PLACEMENT, + DVONN_PHASE_MOVEMENT +} dvonn_phase_t; + typedef struct { dvonn_cell_t cells[DVONN_BOARD_X_SIZE][DVONN_BOARD_Y_SIZE]; - + dvonn_phase_t phase; dvonn_player_t player; + int moves; } dvonn_board_t; /* Initialize a board for a new game of DVONN. */ void dvonn_board_init (dvonn_board_t *board); +/* Place a piece at (x,y) where (0,0) is at the upper-left corner of + * the board. Returns TRUE if the move is legal and is performed. If + * the move is not legal this function returns FALSE, no change will + * be performed on the board, and *error will be set to a string + * describing why the move is illegal.*/ +int +dvonn_board_place (dvonn_board_t *board, + int x, int y, + char **error); + /* Move a piece from (x1,y1) to (x2,y2) where (0,0) is at the * upper-left corner of the board. Returns TRUE if the move is legal * and is performed. If the move is not legal this function returns diff --git a/dvonn.c b/dvonn.c index e19ea43..d4099d9 100644 --- a/dvonn.c +++ b/dvonn.c @@ -163,14 +163,17 @@ on_button_press_event (GtkWidget *widget, if (game->board.cells[x][y].type == DVONN_CELL_INVALID) return TRUE; - if (game->board.cells[x][y].type == DVONN_CELL_EMPTY) - game->board.cells[x][y].type = DVONN_CELL_WHITE; - else if (game->board.cells[x][y].type == DVONN_CELL_WHITE) - game->board.cells[x][y].type = DVONN_CELL_EMPTY; - - dvonn_game_update_windows (game); + if (game->board.phase == DVONN_PHASE_PLACEMENT) { + if (dvonn_board_place (&game->board, x, y, &error)) + dvonn_game_update_windows (game); + else + printf ("Illegal placement %c%d: %s\n", + 'a' + x, + y + 1, + error); - return TRUE; + return TRUE; + } if (! game->has_selected) { if (game->board.cells[x][y].type == game->board.player) { @@ -182,8 +185,7 @@ on_button_press_event (GtkWidget *widget, return TRUE; } - if (x == game->selected_x && - y == game->selected_y) + if (x == game->selected_x && y == game->selected_y) { game->has_selected = FALSE; dvonn_game_update_windows (game); @@ -200,9 +202,9 @@ on_button_press_event (GtkWidget *widget, } else { printf ("Illegal move %c%d%c%d: %s\n", 'a' + game->selected_x, - DVONN_BOARD_Y_SIZE - game->selected_y, + game->selected_y + 1, 'a' + x, - DVONN_BOARD_Y_SIZE - y, + y + 1, error); } @@ -270,10 +272,21 @@ on_expose_event_draw (GtkWidget *widget, x + (y - DVONN_BOARD_Y_SIZE/2) / 2.0, M_SQRT1_2 * y); ring_path (cr); - if (cell.type == DVONN_CELL_WHITE) + switch (cell.type) { + case DVONN_CELL_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ - else + break; + case DVONN_CELL_BLACK: + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ + break; + case DVONN_CELL_RED: + cairo_set_source_rgb (cr, 0.8, 0.2, 0.2); /* red */ + break; + case DVONN_CELL_EMPTY: + default: cairo_set_source_rgba (cr, 0.0, 0.0, 0.2, 0.1); + break; + } cairo_fill (cr); cairo_restore (cr); -- 2.43.0