]> git.cworth.org Git - dvonn/commitdiff
Implement placement phase of game
authorCarl Worth <cworth@cworth.org>
Thu, 5 Mar 2009 09:03:05 +0000 (01:03 -0800)
committerCarl Worth <cworth@cworth.org>
Thu, 5 Mar 2009 09:03:05 +0000 (01:03 -0800)
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
dvonn-board.h
dvonn.c

index 35789e7d13a238748dd3b07e5a95aed218ed0d95..795ff5531d6ed2726e4b24907ccbb5ecbc5fe96f 100644 (file)
@@ -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;
 
index c1c82707c180904fd7a96387a86fbc27716a2b1c..b0ee8cc46a449dfd5d7d4f4201b68140520567fe 100644 (file)
@@ -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 e19ea437e435ee262c3a1407641e095c6888e528..d4099d9984505656984668d3a7d9c72d45c41cce 100644 (file)
--- 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);