* Author: Carl Worth <cworth@cworth.org>
*/
+#include "loudgame.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
+#include <ctype.h>
#include <assert.h>
typedef struct board {
int num_slots;
slot_t slots[BOARD_MAX_SLOTS];
- int needs_deal;
int sets_possible;
- int display_sets_possible;
} board_t;
-typedef struct game {
+typedef struct _set_game {
+ loudgame_t lg;
deck_t deck;
board_t board;
-} game_t;
-
-static void game_init (game_t *game);
-static void game_fini (game_t *game);
+} set_game_t;
static void
board_count_sets_possible (board_t *board);
+static int
+set_game_shuffle (set_game_t *game);
+
+static void
+set_game_new_game (set_game_t *game);
+
static int
attribute_all_same (card_t *cards, int num_cards, int attr)
{
return 1;
}
-static int
-check_selected_for_set (board_t *board)
-{
- int i, num_selected;
- card_t cards[3];
-
- num_selected = 0;
- for (i=0; i < board->num_slots; i++) {
- if (board->slots[i].selected) {
- if (num_selected >= 3)
- return 0;
- cards[num_selected++] = board->slots[i].card;
- }
- }
-
- if (num_selected !=3)
- return 0;
-
- if (! is_set (cards, num_selected))
- return 0;
-
- board_count_sets_possible (board);
-
- board->needs_deal = 1;
-
- return 1;
-}
-
static void
deck_shuffle (deck_t *deck)
{
board->slots[i].has_card = 0;
board->slots[i].selected = 0;
}
- board->needs_deal = 0;
board_count_sets_possible (board);
}
-static void
-board_print (board_t *board)
-{
- int i, j;
-
- printf ("Sets possible: %d\n", board->sets_possible);
-
- for (i = 0; i < board->num_slots; i++) {
- if (! board->slots[i].has_card)
- for (j = 0; j < NUM_ATTRIBUTES; j++)
- printf (" ");
- else
- for (j = 0; j < NUM_ATTRIBUTES; j++)
- printf ("%d", board->slots[i].card.attributes[j]);
- if ((i + 1) % 3 == 0)
- printf ("\n");
- else
- printf (" ");
- }
-}
-
static void
deal (deck_t *deck, board_t *board)
{
}
board_count_sets_possible (board);
+}
+
+static void
+set_game_handle_show (set_game_t *game,
+ const char *peer)
+{
+ board_t *board = &game->board;
+ char board_str[BOARD_MAX_SLOTS * (NUM_ATTRIBUTES + 1)];
+ char *s;
+ int i, j;
+
+ s = board_str;
+ for (i = 0; i < board->num_slots; i++) {
+ if (board->slots[i].has_card) {
+ for (j = 0; j < NUM_ATTRIBUTES; j++)
+ *s++ = '0' + board->slots[i].card.attributes[j];
+ *s++ = ' ';
+ } else {
+ *s++ = '-';
+ *s++ = '-';
+ *s++ = '-';
+ *s++ = ' ';
+ }
+ }
+ *s = '\0';
+
+ loudgame_send (&game->lg, peer, board_str);
+}
+
+static void
+set_game_handle_hint (set_game_t *game,
+ const char *peer)
+{
+ loudgame_sendf (&game->lg, peer, "Sets possible: %d",
+ game->board.sets_possible);
+}
+
+static void
+set_game_handle_shuffle (set_game_t *game,
+ const char *peer)
+{
+ if (game->board.sets_possible) {
+ loudgame_sendf (&game->lg, peer,
+ "There are %d sets, refusing to shuffle.",
+ game->board.sets_possible);
+ return;
+ }
- board->needs_deal = 0;
+ if (game->deck.num_cards == 0) {
+ loudgame_sendf (&game->lg, peer,
+ "Deck exhausted, starting a new game.");
+ set_game_new_game (game);
+ } else {
+ set_game_shuffle (game);
+ }
+}
+
+static void
+set_game_handle_set (set_game_t *game,
+ const char *peer,
+ const char *message)
+{
+ const char *s;
+ char *end = NULL;
+ int i;
+ int slots[3];
+ card_t cards[3];
+
+ s = message;
+ i = 0;
+ while (*s && i < 3) {
+ slots[i++] = strtoul (s, &end, 10);
+ if (end == s) {
+ loudgame_sendf (&game->lg, peer,
+ "Error: Not an integer: %s", s);
+ return;
+ }
+ s = end;
+ }
+
+ while (end && *end && isspace (*end))
+ end++;
+
+ if (i != 3 || *end != '\0') {
+ loudgame_sendf (&game->lg, peer,
+ "Error: The 'set' command requires exactly 3 integers");
+ return;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (slots[i] < 0 || slots[i] > BOARD_MAX_SLOTS) {
+ loudgame_sendf (&game->lg, peer,
+ "Error: Value %d is out of range (0-%d)",
+ slots[i], BOARD_MAX_SLOTS);
+ return;
+ }
+ }
+
+ if (slots[0] == slots[1] ||
+ slots[0] == slots[2] ||
+ slots[1] == slots[2])
+ {
+ loudgame_sendf (&game->lg, peer,
+ "Error: All 3 values must be unique");
+ return;
+ }
+
+ for (i=0; i < 3; i++) {
+ if (game->board.slots[slots[i]].has_card) {
+ cards[i] = game->board.slots[slots[i]].card;
+ } else {
+ loudgame_sendf (&game->lg, peer,
+ "Error: There's no card at position %d", i);
+ return;
+ }
+ }
+
+ if (! is_set (cards, 3)) {
+ loudgame_sendf (&game->lg, peer,
+ "Sorry, that's not a set");
+ return;
+ }
+
+ loudgame_sendf (&game->lg, peer,
+ "Yes, that's a set!");
+
+ for (i = 0; i < 3; i++)
+ game->board.slots[slots[i]].has_card = 0;
+
+ board_count_sets_possible (&game->board);
+
+ deal (&game->deck, &game->board);
+}
+
+static void
+set_game_handle_message (loudgame_t *lg,
+ const char *peer,
+ const char *message)
+{
+ set_game_t *game = (set_game_t*) lg;
+
+ if (strcmp (message, "show") == 0)
+ set_game_handle_show (game, peer);
+ else if (strcmp (message, "hint") == 0)
+ set_game_handle_hint (game, peer);
+ else if (strcmp (message, "shuffle") == 0)
+ set_game_handle_shuffle (game, peer);
+ else if (strncmp (message, "set", 3) == 0)
+ set_game_handle_set (game, peer, message + 3);
+ else
+ loudgame_sendf (lg, peer, "Unknown command: '%s'", message);
}
/* Begin a new game */
static void
-game_init (game_t *game)
+set_game_new_game (set_game_t *game)
{
deck_init (&game->deck);
board_init (&game->board);
deal (&game->deck, &game->board);
}
-static void
-game_fini (game_t *game)
+static int
+set_game_init (set_game_t *game, int argc, char *argv[])
{
- /* Nothing to do. */
+ int err;
+
+ err = loudgame_init (&game->lg, argc, argv);
+ if (err)
+ return err;
+
+ set_game_new_game (game);
+
+ return 0;
}
/* Return the dealt cards to the deck, reshuffle, and deal again. */
static int
-reshuffle (deck_t *deck, board_t *board)
+set_game_shuffle (set_game_t *game)
{
+ board_t *board = &game->board;
+ deck_t *deck = &game->deck;
int i;
- if (board->sets_possible) {
- return 0;
- }
-
for (i=0; i < board->num_slots; i++) {
if (board->slots[i].has_card) {
deck->cards[++deck->num_cards - 1] = board->slots[i].card;
}
int
-main (void)
+main (int argc, char *argv[])
{
- game_t game;
+ set_game_t game;
+ int err;
srand (time(0));
- game_init (&game);
+ err = set_game_init (&game, argc, argv);
+ if (err)
+ return err;
- board_print (&game.board);
+ game.lg.handle_message = set_game_handle_message;
- game_fini (&game);
+ err = loudgame_run (&game.lg);
+ if (err)
+ return err;
return 0;
}