]> git.cworth.org Git - dvonn/blob - dvonn-board.c
Add visual indication of selected stack
[dvonn] / dvonn-board.c
1 /*
2  * Copyright (C) 2009 Carl Worth
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see http://www.gnu.org/licenses/ .
16  *
17  * Author: Carl Worth <cworth@cworth.org>
18  */
19
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <assert.h>
23
24 #include <glib.h>
25
26 #include "dvonn-board.h"
27
28 /* Just a diagram to help start thinking about data structures:
29  *
30  * Played/drawn as:
31  *
32  *   1 ○ ○ ○ ○ ○ ○ ○ ○ ○
33  *  2 ○ ● ● ○ ○ ○ ○ ○ ○ ○
34  * 3 ○ ● ○ ● ○ ○ ○ ○ ○ ○ ○
35  *  4 ○ ● ● ○ ○ ○ ○ ○ ○ ○ K
36  *   5 ○ ○ ○ ○ ○ ○ ○ ○ ○ J
37  *      A B C D E F G H I
38  *
39  * Stored as:
40  *
41  * 1 x x ○ ○ ○ ○ ○ ○ ○ ○ ○
42  * 2 x ○ ● ● ○ ○ ○ ○ ○ ○ ○
43  * 3 ○ ● ○ ● ○ ○ ○ ○ ○ ○ ○
44  * 4 ○ ● ● ○ ○ ○ ○ ○ ○ ○ x
45  * 5 ○ ○ ○ ○ ○ ○ ○ ○ ○ x x
46  *   A B C D E F G H I J K
47  *
48  * With connections as:
49  *
50  *         C2  D2
51  *          | /
52  *  B3 <-> C3 <-> D3
53  *        / |
54  *      B2 C4
55  */
56
57 void
58 dvonn_board_init (dvonn_board_t *board)
59 {
60     int x, y;
61
62     for (x = 0; x < DVONN_BOARD_X_SIZE; x++) {
63         for (y = 0; y < DVONN_BOARD_Y_SIZE; y++) {
64             board->cells[x][y].type = DVONN_CELL_EMPTY;
65             board->cells[x][y].height = 0;
66         }
67     }
68
69     /* Cut out the unplayable "corners" of the board. */
70     for (x = 0; x < DVONN_BOARD_Y_SIZE / 2; x++) {
71         for (y = 0; y < (DVONN_BOARD_Y_SIZE / 2) - x; y++) {
72             board->cells[x][y].type = DVONN_CELL_INVALID;
73             board->cells
74                 [DVONN_BOARD_X_SIZE-1-x]
75                 [DVONN_BOARD_Y_SIZE-1-y].type = DVONN_CELL_INVALID;
76         }
77     }
78
79     board->phase = DVONN_PHASE_PLACEMENT;
80     board->player = DVONN_PLAYER_WHITE;
81     board->moves = 0;
82 }
83
84 static dvonn_bool_t
85 dvonn_board_move_legal (dvonn_board_t *board,
86                         int x1, int y1,
87                         int x2, int y2,
88                         char **error)
89 {
90     if (x1 < 0 || x1 >= DVONN_BOARD_X_SIZE ||
91         y1 < 0 || y1 >= DVONN_BOARD_Y_SIZE ||
92         x2 < 0 || x2 >= DVONN_BOARD_X_SIZE ||
93         y2 < 0 || y2 >= DVONN_BOARD_Y_SIZE)
94     {
95         *error = "Invalid coordinates (not on board)";
96         return FALSE;
97     }
98
99     if (board->cells[x1][y1].type == DVONN_CELL_INVALID) {
100         *error = "Not a valid board space";
101         return FALSE;
102     }
103
104     if (board->cells[x1][y1].type == DVONN_CELL_EMPTY) {
105         *error = "There is no piece there to move";
106         return FALSE;
107     }
108
109     if (board->cells[x1][y1].type != board->player) {
110         *error = "You cannot move your opponent's piece";
111         return FALSE;
112     }
113
114     /* XXX: Need to code up DVONN-legal move calculation here. */
115
116     return TRUE;
117 }
118
119 static void
120 dvonn_board_next_player (dvonn_board_t *board)
121 {
122     if (board->player == DVONN_PLAYER_BLACK)
123         board->player = DVONN_PLAYER_WHITE;
124     else
125         board->player = DVONN_PLAYER_BLACK;
126 }
127
128 int
129 dvonn_board_place (dvonn_board_t *board,
130                    int x, int y,
131                    char **error)
132 {
133     if (board->phase != DVONN_PHASE_PLACEMENT) {
134         *error = "Cannot place outside of placement phase";
135         return FALSE;
136     }
137
138     if (board->cells[x][y].type != DVONN_CELL_EMPTY) {
139         *error = "Cannot place on an occupied space";
140         return FALSE;
141     }
142
143     if (board->moves < 3)
144         board->cells[x][y].type = DVONN_CELL_RED;
145     else if (board->moves % 2)
146         board->cells[x][y].type = DVONN_CELL_BLACK;
147     else
148         board->cells[x][y].type = DVONN_CELL_WHITE;
149
150     board->moves++;
151
152     if (board->moves == 49) {
153         board->phase = DVONN_PHASE_MOVEMENT;
154         board->moves = 0;
155     }
156
157     return TRUE;
158 }
159
160 int
161 dvonn_board_move (dvonn_board_t *board,
162                   int x1, int y1,
163                   int x2, int y2,
164                   char **error)
165 {
166     if (board->phase != DVONN_PHASE_MOVEMENT) {
167         *error = "Cannot move outside of placement phase";
168         return FALSE;
169     }
170
171     if (! dvonn_board_move_legal (board, x1, y1, x2, y2, error))
172         return FALSE;
173
174     /* XXX: Need to execute the move here. */
175
176     dvonn_board_next_player (board);
177
178     return TRUE;
179 }