Add support for claiming a set.
authorCarl Worth <cworth@cworth.org>
Fri, 18 Jan 2008 08:19:40 +0000 (00:19 -0800)
committerCarl Worth <cworth@cworth.org>
Fri, 18 Jan 2008 08:19:40 +0000 (00:19 -0800)
And tons of input validation.

lg-set.c

index af51bd864a3857365e12cc1a5db6bd229dedf4ad..c5ebbfb67b7f199d0347cb2ae3846fbeabea4b0c 100644 (file)
--- a/lg-set.c
+++ b/lg-set.c
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <math.h>
 #include <time.h>
+#include <ctype.h>
 
 #include <assert.h>
 
@@ -75,7 +76,6 @@ typedef struct slot {
 typedef struct board {
     int num_slots;
     slot_t slots[BOARD_MAX_SLOTS];
-    int needs_deal;
     int sets_possible;
 } board_t;
 
@@ -91,6 +91,9 @@ 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)
 {
@@ -142,34 +145,6 @@ is_set (card_t *cards, int num_cards)
     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)
 {
@@ -250,7 +225,6 @@ board_init (board_t *board)
        board->slots[i].has_card = 0;
        board->slots[i].selected = 0;
     }
-    board->needs_deal = 0;
 
     board_count_sets_possible (board);
 }
@@ -269,8 +243,6 @@ deal (deck_t *deck, board_t *board)
        }
 
     board_count_sets_possible (board);
-
-    board->needs_deal = 0;
 }
 
 static void
@@ -313,7 +285,90 @@ set_game_handle_shuffle (set_game_t *game,
        return;
     }
 
-    set_game_shuffle (game);
+    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
@@ -329,11 +384,21 @@ set_game_handle_message (loudgame_t *lg,
        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
+set_game_new_game (set_game_t *game)
+{
+    deck_init (&game->deck);
+    board_init (&game->board);
+    deal (&game->deck, &game->board);
+}
+
 static int
 set_game_init (set_game_t *game, int argc, char *argv[])
 {
@@ -343,9 +408,7 @@ set_game_init (set_game_t *game, int argc, char *argv[])
     if (err)
        return err;
 
-    deck_init (&game->deck);
-    board_init (&game->board);
-    deal (&game->deck, &game->board);
+    set_game_new_game (game);
 
     return 0;
 }