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.
+ board->phase = DVONN_PHASE_PLACEMENT;
board->player = DVONN_PLAYER_WHITE;
board->player = DVONN_PLAYER_WHITE;
board->player = DVONN_PLAYER_BLACK;
}
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)
{
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;
if (! dvonn_board_move_legal (board, x1, y1, x2, y2, error))
return FALSE;
typedef enum {
DVONN_CELL_BLACK = DVONN_PLAYER_BLACK,
DVONN_CELL_WHITE = DVONN_PLAYER_WHITE,
typedef enum {
DVONN_CELL_BLACK = DVONN_PLAYER_BLACK,
DVONN_CELL_WHITE = DVONN_PLAYER_WHITE,
DVONN_CELL_EMPTY,
DVONN_CELL_INVALID
} dvonn_cell_type_t;
DVONN_CELL_EMPTY,
DVONN_CELL_INVALID
} dvonn_cell_type_t;
#define DVONN_BOARD_X_SIZE 11
#define DVONN_BOARD_Y_SIZE 5
#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];
typedef struct {
dvonn_cell_t cells[DVONN_BOARD_X_SIZE][DVONN_BOARD_Y_SIZE];
} dvonn_board_t;
/* Initialize a board for a new game of DVONN. */
void
dvonn_board_init (dvonn_board_t *board);
} 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
/* 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
if (game->board.cells[x][y].type == DVONN_CELL_INVALID)
return TRUE;
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);
if (! game->has_selected) {
if (game->board.cells[x][y].type == game->board.player) {
if (! game->has_selected) {
if (game->board.cells[x][y].type == game->board.player) {
- 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);
{
game->has_selected = FALSE;
dvonn_game_update_windows (game);
} else {
printf ("Illegal move %c%d%c%d: %s\n",
'a' + game->selected_x,
} else {
printf ("Illegal move %c%d%c%d: %s\n",
'a' + game->selected_x,
- DVONN_BOARD_Y_SIZE - game->selected_y,
- DVONN_BOARD_Y_SIZE - y,
x + (y - DVONN_BOARD_Y_SIZE/2) / 2.0,
M_SQRT1_2 * y);
ring_path (cr);
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 */
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+ 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);
cairo_set_source_rgba (cr, 0.0, 0.0, 0.2, 0.1);
cairo_fill (cr);
cairo_restore (cr);
cairo_fill (cr);
cairo_restore (cr);