More serialisation changes: the game_aux_info structure has now been
[sgt/puzzles] / guess.c
diff --git a/guess.c b/guess.c
index 35cfb5b..613bc59 100644 (file)
--- a/guess.c
+++ b/guess.c
@@ -60,11 +60,6 @@ static game_params *default_params(void)
     return ret;
 }
 
-static int game_fetch_preset(int i, char **name, game_params **params)
-{
-    return FALSE;
-}
-
 static void free_params(game_params *params)
 {
     sfree(params);
@@ -77,6 +72,32 @@ static game_params *dup_params(game_params *params)
     return ret;
 }
 
+static const struct {
+    char *name;
+    game_params params;
+} guess_presets[] = {
+    {"Standard", {6, 4, 10, FALSE, TRUE}},
+    {"Super", {8, 5, 12, FALSE, TRUE}},
+};
+
+
+static int game_fetch_preset(int i, char **name, game_params **params)
+{
+    if (i < 0 || i >= lenof(guess_presets))
+        return FALSE;
+
+    *name = dupstr(guess_presets[i].name);
+    /*
+     * get round annoying const issues
+     */
+    {
+        game_params tmp = guess_presets[i].params;
+        *params = dup_params(&tmp);
+    }
+
+    return TRUE;
+}
+
 static void decode_params(game_params *params, char const *string)
 {
     char const *p = string;
@@ -243,7 +264,7 @@ static void free_pegrow(pegrow pegs)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     unsigned char *bmp = snewn(params->npegs, unsigned char);
     char *ret;
@@ -265,11 +286,6 @@ newcol:
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     unsigned char *bmp;
@@ -343,12 +359,10 @@ static void free_game(game_state *state)
     sfree(state);
 }
 
-static game_state *solve_game(game_state *state, game_state *currstate,
-                              game_aux_info *aux, char **error)
+static char *solve_game(game_state *state, game_state *currstate,
+                       char *aux, char **error)
 {
-    game_state *ret = dup_game(currstate);
-    ret->solved = 1;
-    return ret;
+    return dupstr("S");
 }
 
 static char *game_text_format(game_state *state)
@@ -385,6 +399,15 @@ static void free_ui(game_ui *ui)
     sfree(ui);
 }
 
+char *encode_ui(game_ui *ui)
+{
+    return NULL;
+}
+
+void decode_ui(game_ui *ui, char *encoding)
+{
+}
+
 static void game_changed_state(game_ui *ui, game_state *oldstate,
                                game_state *newstate)
 {
@@ -527,47 +550,52 @@ static int mark_pegs(pegrow guess, pegrow solution, int ncols)
     return nc_place;
 }
 
-static game_state *mark_move(game_state *from, game_ui *ui)
+static char *encode_move(game_state *from, game_ui *ui)
 {
-    int i, ncleared = 0, nc_place;
-    game_state *to = dup_game(from);
-
-    for (i = 0; i < to->solution->npegs; i++) {
-        to->guesses[from->next_go]->pegs[i] = ui->curr_pegs->pegs[i];
+    char *buf, *p, *sep;
+    int len, i, solved;
+    pegrow tmppegs;
+
+    len = ui->curr_pegs->npegs * 20 + 2;
+    buf = snewn(len, char);
+    p = buf;
+    *p++ = 'G';
+    sep = "";
+    for (i = 0; i < ui->curr_pegs->npegs; i++) {
+       p += sprintf(p, "%s%d", sep, ui->curr_pegs->pegs[i]);
+       sep = ",";
     }
-    nc_place = mark_pegs(to->guesses[from->next_go], to->solution, to->params.ncolours);
-
-    if (nc_place == to->solution->npegs) {
-        to->solved = 1; /* win! */
-    } else {
-        to->next_go = from->next_go + 1;
-        if (to->next_go >= to->params.nguesses)
-            to->solved = 1; /* 'lose' so we show the pegs. */
-    }
-
-    for (i = 0; i < to->solution->npegs; i++) {
-        if (!ui->holds[i] || to->solved) {
-            ui->curr_pegs->pegs[i] = 0;
-            ncleared++;
-        }
-        if (to->solved) ui->holds[i] = 0;
+    *p++ = '\0';
+    assert(p - buf <= len);
+    buf = sresize(buf, len, char);
+
+    tmppegs = dup_pegrow(ui->curr_pegs);
+    solved = mark_pegs(tmppegs, from->solution, from->params.ncolours);
+    solved = (solved == from->params.ncolours);
+    free_pegrow(tmppegs);
+
+    for (i = 0; i < from->solution->npegs; i++) {
+       if (!ui->holds[i] || solved) {
+           ui->curr_pegs->pegs[i] = 0;
+       }
+       if (solved) ui->holds[i] = 0;
     }
     ui->markable = is_markable(&from->params, ui->curr_pegs);
-    if (!ui->markable && ui->peg_cur == to->solution->npegs)
-        ui->peg_cur--;
+    if (!ui->markable && ui->peg_cur == from->solution->npegs)
+       ui->peg_cur--;
 
-    return to;
+    return buf;
 }
 
-static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
-                             int x, int y, int button)
+static char *interpret_move(game_state *from, game_ui *ui, game_drawstate *ds,
+                           int x, int y, int button)
 {
     int over_col = 0;           /* one-indexed */
     int over_guess = -1;        /* zero-indexed */
     int over_past_guess_y = -1; /* zero-indexed */
     int over_past_guess_x = -1; /* zero-indexed */
     int over_hint = 0;          /* zero or one */
-    game_state *ret = NULL;
+    char *ret = NULL;
 
     int guess_ox = GUESS_X(from->next_go, 0);
     int guess_oy = GUESS_Y(from->next_go, 0);
@@ -622,13 +650,13 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
             ui->drag_y = y;
             debug(("Start dragging, col = %d, (%d,%d)",
                    ui->drag_col, ui->drag_x, ui->drag_y));
-            ret = from;
+            ret = "";
         }
     } else if (button == LEFT_DRAG && ui->drag_col) {
         ui->drag_x = x;
         ui->drag_y = y;
         debug(("Keep dragging, (%d,%d)", ui->drag_x, ui->drag_y));
-        ret = from;
+        ret = "";
     } else if (button == LEFT_RELEASE && ui->drag_col) {
         if (over_guess > -1) {
             debug(("Dropping colour %d onto guess peg %d",
@@ -645,18 +673,18 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
         ui->drag_opeg = -1;
         ui->display_cur = 0;
         debug(("Stop dragging."));
-        ret = from;
+        ret = "";
     } else if (button == RIGHT_BUTTON) {
         if (over_guess > -1) {
             /* we use ths feedback in the game_ui to signify
              * 'carry this peg to the next guess as well'. */
             ui->holds[over_guess] = 1 - ui->holds[over_guess];
-            ret = from;
+            ret = "";
         }
     } else if (button == LEFT_RELEASE && over_hint && ui->markable) {
         /* NB this won't trigger if on the end of a drag; that's on
          * purpose, in case you drop by mistake... */
-        ret = mark_move(from, ui);
+        ret = encode_move(from, ui);
     }
 
     /* keyboard input */
@@ -666,7 +694,7 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
             ui->colour_cur++;
         if (button == CURSOR_UP && ui->colour_cur > 0)
             ui->colour_cur--;
-        ret = from;
+        ret = "";
     } else if (button == CURSOR_LEFT || button == CURSOR_RIGHT) {
         int maxcur = from->params.npegs;
         if (ui->markable) maxcur++;
@@ -676,22 +704,65 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
             ui->peg_cur++;
         if (button == CURSOR_LEFT && ui->peg_cur > 0)
             ui->peg_cur--;
-        ret = from;
+        ret = "";
     } else if (button == CURSOR_SELECT || button == ' ' || button == '\r' ||
                button == '\n') {
+        ui->display_cur = 1;
         if (ui->peg_cur == from->params.npegs) {
-            ret = mark_move(from, ui);
+            ret = encode_move(from, ui);
         } else {
             set_peg(&from->params, ui, ui->peg_cur, ui->colour_cur+1);
-            ret = from;
+            ret = "";
         }
     } else if (button == 'H' || button == 'h') {
+        ui->display_cur = 1;
         ui->holds[ui->peg_cur] = 1 - ui->holds[ui->peg_cur];
-        ret = from;
+        ret = "";
     }
     return ret;
 }
 
+static game_state *execute_move(game_state *from, char *move)
+{
+    int i, nc_place;
+    game_state *ret;
+    char *p;
+
+    if (!strcmp(move, "S")) {
+       ret = dup_game(from);
+       ret->solved = 1;
+       return ret;
+    } else if (move[0] == 'G') {
+       p = move+1;
+
+       ret = dup_game(from);
+
+       for (i = 0; i < from->solution->npegs; i++) {
+           int val = atoi(p);
+           if (val <= 0 || val > from->params.ncolours) {
+               free_game(ret);
+               return NULL;
+           }
+           ret->guesses[from->next_go]->pegs[i] = atoi(p);
+           while (*p && isdigit((unsigned char)*p)) p++;
+           if (*p == ',') p++;
+       }
+
+       nc_place = mark_pegs(ret->guesses[from->next_go], ret->solution, ret->params.ncolours);
+
+       if (nc_place == ret->solution->npegs) {
+           ret->solved = 1; /* win! */
+       } else {
+           ret->next_go = from->next_go + 1;
+           if (ret->next_go >= ret->params.nguesses)
+               ret->solved = 1; /* 'lose' so we show the pegs. */
+       }
+
+       return ret;
+    } else
+       return NULL;
+}
+
 /* ----------------------------------------------------------------------
  * Drawing routines.
  */
@@ -1184,7 +1255,6 @@ const struct game thegame = {
     TRUE, game_configure, custom_params,
     validate_params,
     new_game_desc,
-    game_free_aux_info,
     validate_desc,
     new_game,
     dup_game,
@@ -1193,8 +1263,11 @@ const struct game thegame = {
     FALSE, game_text_format,
     new_ui,
     free_ui,
+    encode_ui,
+    decode_ui,
     game_changed_state,
-    make_move,
+    interpret_move,
+    execute_move,
     game_size,
     game_colours,
     game_new_drawstate,