2 * Copyright (C) 2008 Carl Worth
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.
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.
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/ .
17 * Author: Carl Worth <cworth@cworth.org>
29 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
31 #define NUM_ATTRIBUTES 4
34 char *attribute_names[NUM_ATTRIBUTES] = {
35 "number", "color", "shading", "symbol"
38 typedef enum { ATTRIBUTE_INDEX_NUMBER,
39 ATTRIBUTE_INDEX_COLOR,
40 ATTRIBUTE_INDEX_SHADING,
41 ATTRIBUTE_INDEX_SYMBOL } attribute_index_t;
43 char *attribute_values[NUM_ATTRIBUTES][NUM_VALUES] = {
45 { "red", "green", "purple" },
46 { "solid", "open", "striped" },
47 { "oval", "squiggle", "diamond" }
50 typedef enum { COLOR_RED, COLOR_GREEN, COLOR_PURPLE } color_t;
51 typedef enum { SHADING_OPEN, SHADING_STRIPED, SHADING_SOLID } shading_t;
52 typedef enum { SYMBOL_OVAL, SYMBOL_SQUIGGLE, SYMBOL_DIAMOND } symbol_t;
55 int attributes[NUM_ATTRIBUTES];
58 #define DECK_MAX_CARDS ((int) (pow (NUM_VALUES, NUM_ATTRIBUTES)))
61 card_t cards[DECK_MAX_CARDS];
72 #define BOARD_MAX_SLOTS (BOARD_COLS * BOARD_ROWS)
73 typedef struct board {
75 slot_t slots[BOARD_MAX_SLOTS];
78 int display_sets_possible;
86 static void game_init (game_t *game);
87 static void game_fini (game_t *game);
90 board_count_sets_possible (board_t *board);
93 attribute_all_same (card_t *cards, int num_cards, int attr)
100 value = cards[0].attributes[attr];
102 for (i = 1; i < num_cards; i++)
103 if (cards[i].attributes[attr] != value)
110 attribute_all_different (card_t *cards, int num_cards, int attr)
112 int i, seen[NUM_VALUES];
117 memset (seen, 0, sizeof (seen));
119 for (i = 0; i < num_cards; i++) {
120 if (seen[cards[i].attributes[attr]])
122 seen[cards[i].attributes[attr]] = 1;
129 is_set (card_t *cards, int num_cards)
133 for (attr = 0; attr < NUM_ATTRIBUTES; attr++)
134 if (! attribute_all_same (cards, num_cards, attr) &&
135 ! attribute_all_different (cards, num_cards, attr))
144 check_selected_for_set (board_t *board)
150 for (i=0; i < board->num_slots; i++) {
151 if (board->slots[i].selected) {
152 if (num_selected >= 3)
154 cards[num_selected++] = board->slots[i].card;
158 if (num_selected !=3)
161 if (! is_set (cards, num_selected))
164 board_count_sets_possible (board);
166 board->needs_deal = 1;
172 deck_shuffle (deck_t *deck)
177 assert (deck->num_cards <= DECK_MAX_CARDS);
179 for (i=deck->num_cards - 1; i>=0; i--) {
180 r = (int) i * (rand() / (RAND_MAX + 1.0));
183 tmp = deck->cards[i];
184 deck->cards[i] = deck->cards[r];
185 deck->cards[r] = tmp;
190 deck_init (deck_t *deck)
199 for (number = 0; number < NUM_VALUES; number++)
200 for (color = 0; color < NUM_VALUES; color++)
201 for (shading = 0; shading < NUM_VALUES; shading++)
202 for (symbol = 0; symbol < NUM_VALUES; symbol++) {
203 deck->cards[card].attributes[ATTRIBUTE_INDEX_NUMBER] = number;
204 deck->cards[card].attributes[ATTRIBUTE_INDEX_COLOR] = color;
205 deck->cards[card].attributes[ATTRIBUTE_INDEX_SHADING] = shading;
206 deck->cards[card].attributes[ATTRIBUTE_INDEX_SYMBOL] = symbol;
209 deck->num_cards = card;
215 board_count_sets_possible (board_t *board)
218 int sets_possible = 0;
221 for (i = 0; i < board->num_slots; i++) {
222 if (! board->slots[i].has_card)
224 for (j = i+1; j < board->num_slots; j++) {
225 if (! board->slots[j].has_card)
227 for (k = j+1; k < board->num_slots; k++) {
228 if (! board->slots[k].has_card)
230 cards[0] = board->slots[i].card;
231 cards[1] = board->slots[j].card;
232 cards[2] = board->slots[k].card;
233 if (is_set (cards, 3))
239 board->sets_possible = sets_possible;
243 board_init (board_t *board)
246 board->num_slots = BOARD_MAX_SLOTS;
247 for (i=0; i < board->num_slots; i++) {
248 board->slots[i].has_card = 0;
249 board->slots[i].selected = 0;
251 board->needs_deal = 0;
253 board_count_sets_possible (board);
257 board_print (board_t *board)
261 printf ("Sets possible: %d\n", board->sets_possible);
263 for (i = 0; i < board->num_slots; i++) {
264 if (! board->slots[i].has_card)
265 for (j = 0; j < NUM_ATTRIBUTES; j++)
268 for (j = 0; j < NUM_ATTRIBUTES; j++)
269 printf ("%d", board->slots[i].card.attributes[j]);
270 if ((i + 1) % 3 == 0)
278 deal (deck_t *deck, board_t *board)
282 for (i=0; i < board->num_slots; i++)
283 if (! board->slots[i].has_card) {
284 if (deck->num_cards > 0) {
285 board->slots[i].card = deck->cards[deck->num_cards-- -1];
286 board->slots[i].has_card = 1;
290 board_count_sets_possible (board);
292 board->needs_deal = 0;
295 /* Begin a new game */
297 game_init (game_t *game)
299 deck_init (&game->deck);
300 board_init (&game->board);
301 deal (&game->deck, &game->board);
305 game_fini (game_t *game)
310 /* Return the dealt cards to the deck, reshuffle, and deal again. */
312 reshuffle (deck_t *deck, board_t *board)
316 if (board->sets_possible) {
320 for (i=0; i < board->num_slots; i++) {
321 if (board->slots[i].has_card) {
322 deck->cards[++deck->num_cards - 1] = board->slots[i].card;
323 board->slots[i].has_card = 0;
324 board->slots[i].selected = 0;
343 board_print (&game.board);