Introduce routines in each game module to encode a set of game
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 19 May 2004 11:57:09 +0000 (11:57 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 19 May 2004 11:57:09 +0000 (11:57 +0000)
parameters as a string, and decode it again. This is used in
midend.c to prepend the game parameters to the game seed, so that
copying out of the Specific box is sufficient to completely specify
the game you were playing.
Throughout development of these games I have referred to `seed'
internally, and `game ID' externally. Now there's a measurable
difference between them! :-)

git-svn-id: svn://svn.tartarus.org/sgt/puzzles@4231 cda61777-01e9-0310-a592-d414129be87e

cube.c
fifteen.c
midend.c
net.c
nullgame.c
puzzles.h
rect.c
sixteen.c

diff --git a/cube.c b/cube.c
index 2ce7a4f..afd2ebd 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 #include <math.h>
 
 #include "puzzles.h"
@@ -276,6 +277,37 @@ game_params *dup_params(game_params *params)
     return ret;
 }
 
+game_params *decode_params(char const *string)
+{
+    game_params *ret = default_params();
+
+    switch (*string) {
+      case 't': ret->solid = TETRAHEDRON; string++; break;
+      case 'c': ret->solid = CUBE;        string++; break;
+      case 'o': ret->solid = OCTAHEDRON;  string++; break;
+      case 'i': ret->solid = ICOSAHEDRON; string++; break;
+      default: break;
+    }
+    ret->d1 = ret->d2 = atoi(string);
+    while (*string && isdigit(*string)) string++;
+    if (*string == 'x') {
+        string++;
+        ret->d2 = atoi(string);
+    }
+
+    return ret;
+}
+
+char *encode_params(game_params *params)
+{
+    char data[256];
+
+    assert(params->solid >= 0 && params->solid < 4);
+    sprintf(data, "%c%dx%d", "tcoi"[params->solid], params->d1, params->d2);
+
+    return dupstr(data);
+}
+
 static void enum_grid_squares(game_params *params,
                               void (*callback)(void *, struct grid_square *),
                               void *ctx)
@@ -653,7 +685,7 @@ char *new_game_seed(game_params *params, random_state *rs)
     /*
      * Choose a non-blue square for the polyhedron.
      */
-    sprintf(p, ":%d", data.gridptrs[0][random_upto(rs, m)]);
+    sprintf(p, ",%d", data.gridptrs[0][random_upto(rs, m)]);
 
     sfree(data.gridptrs[0]);
     sfree(flags);
@@ -824,13 +856,13 @@ char *validate_seed(game_params *params, char *seed)
        /* NB if seed[j]=='\0' that will also be caught here, so we're safe */
     }
 
-    if (seed[i] != ':')
-       return "Expected ':' after hex digits";
+    if (seed[i] != ',')
+       return "Expected ',' after hex digits";
 
     i++;
     do {
        if (seed[i] < '0' || seed[i] > '9')
-           return "Expected decimal integer after ':'";
+           return "Expected decimal integer after ','";
        i++;
     } while (seed[i]);
 
@@ -883,7 +915,7 @@ game_state *new_game(game_params *params, char *seed)
                j = 8;
        }
 
-       if (*p == ':')
+       if (*p == ',')
            p++;
 
        state->current = atoi(p);
index 78060f5..2788604 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 #include <math.h>
 
 #include "puzzles.h"
@@ -72,6 +73,29 @@ game_params *dup_params(game_params *params)
     return ret;
 }
 
+game_params *decode_params(char const *string)
+{
+    game_params *ret = default_params();
+
+    ret->w = ret->h = atoi(string);
+    while (*string && isdigit(*string)) string++;
+    if (*string == 'x') {
+        string++;
+        ret->h = atoi(string);
+    }
+
+    return ret;
+}
+
+char *encode_params(game_params *params)
+{
+    char data[256];
+
+    sprintf(data, "%dx%d", params->w, params->h);
+
+    return dupstr(data);
+}
+
 config_item *game_configure(game_params *params)
 {
     config_item *ret;
index 63ba193..6a93856 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -333,7 +333,7 @@ int midend_wants_statusbar(midend_data *me)
 
 config_item *midend_get_config(midend_data *me, int which, char **wintitle)
 {
-    char *titlebuf;
+    char *titlebuf, *parstr;
     config_item *ret;
 
     titlebuf = snewn(40 + strlen(game_name), char);
@@ -352,7 +352,15 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle)
        ret[0].type = C_STRING;
        ret[0].name = "Game ID";
        ret[0].ival = 0;
-       ret[0].sval = dupstr(me->seed);
+        /*
+         * The text going in here will be a string encoding of the
+         * parameters, plus a colon, plus the game seed. This is a
+         * full game ID.
+         */
+        parstr = encode_params(me->params);
+        ret[0].sval = snewn(strlen(parstr) + strlen(me->seed) + 2, char);
+        sprintf(ret[0].sval, "%s:%s", parstr, me->seed);
+        sfree(parstr);
 
        ret[1].type = C_END;
        ret[1].name = ret[1].sval = NULL;
@@ -367,7 +375,7 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle)
 
 char *midend_set_config(midend_data *me, int which, config_item *cfg)
 {
-    char *error;
+    char *error, *p;
     game_params *params;
 
     switch (which) {
@@ -385,12 +393,34 @@ char *midend_set_config(midend_data *me, int which, config_item *cfg)
        break;
 
       case CFG_SEED:
-       error = validate_seed(me->params, cfg[0].sval);
+
+        /*
+         * The game ID will often (in fact, mostly) have a prefix
+         * containing a string-encoded parameter specification
+         * followed by a colon. So first find the colon, and then
+         * split the string up.
+         */
+        p = strchr(cfg[0].sval, ':');
+
+        if (p) {
+            *p++ = '\0';               /* p now points to game seed */
+            params = decode_params(cfg[0].sval);
+            error = validate_params(params);
+            if (error) {
+                free_params(params);
+                return error;
+            }
+            free_params(me->params);
+            me->params = params;
+        } else
+            p = cfg[0].sval;
+
+       error = validate_seed(me->params, p);
        if (error)
            return error;
 
        sfree(me->seed);
-       me->seed = dupstr(cfg[0].sval);
+       me->seed = dupstr(p);
        me->fresh_seed = TRUE;
 
        break;
diff --git a/net.c b/net.c
index d616d03..3c3f971 100644 (file)
--- a/net.c
+++ b/net.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 #include <math.h>
 
 #include "puzzles.h"
@@ -183,6 +184,44 @@ game_params *dup_params(game_params *params)
     return ret;
 }
 
+game_params *decode_params(char const *string)
+{
+    game_params *ret = default_params();
+    char const *p = string;
+
+    ret->width = atoi(p);
+    while (*p && isdigit(*p)) p++;
+    if (*p == 'x') {
+        p++;
+        ret->height = atoi(p);
+        while (*p && isdigit(*p)) p++;
+        if ( (ret->wrapping = (*p == 'w')) != 0 )
+            p++;
+        if (*p == 'b')
+            ret->barrier_probability = atof(p+1);
+    } else {
+        ret->height = ret->width;
+    }
+
+    return ret;
+}
+
+char *encode_params(game_params *params)
+{
+    char ret[400];
+    int len;
+
+    len = sprintf(ret, "%dx%d", params->width, params->height);
+    if (params->wrapping)
+        ret[len++] = 'w';
+    if (params->barrier_probability)
+        len += sprintf(ret+len, "b%g", params->barrier_probability);
+    assert(len < lenof(ret));
+    ret[len] = '\0';
+
+    return dupstr(ret);
+}
+
 config_item *game_configure(game_params *params)
 {
     config_item *ret;
index 32e6e2c..67982b9 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 #include <math.h>
 
 #include "puzzles.h"
@@ -61,6 +62,20 @@ game_params *dup_params(game_params *params)
     return ret;
 }
 
+game_params *decode_params(char const *string)
+{
+    game_params *ret = snew(game_params);
+
+    ret->FIXME = 0;
+
+    return ret;
+}
+
+char *encode_params(game_params *params)
+{
+    return dupstr("FIXME");
+}
+
 config_item *game_configure(game_params *params)
 {
     return NULL;
index 46c0f15..37c190a 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -162,6 +162,8 @@ extern const char *const game_name;
 const int game_can_configure;
 game_params *default_params(void);
 int game_fetch_preset(int i, char **name, game_params **params);
+game_params *decode_params(char const *string);
+char *encode_params(game_params *);
 void free_params(game_params *params);
 game_params *dup_params(game_params *params);
 config_item *game_configure(game_params *params);
diff --git a/rect.c b/rect.c
index dcd8ef7..9b7816c 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 #include <math.h>
 
 #include "puzzles.h"
@@ -129,6 +130,29 @@ game_params *dup_params(game_params *params)
     return ret;
 }
 
+game_params *decode_params(char const *string)
+{
+    game_params *ret = default_params();
+
+    ret->w = ret->h = atoi(string);
+    while (*string && isdigit(*string)) string++;
+    if (*string == 'x') {
+        string++;
+        ret->h = atoi(string);
+    }
+
+    return ret;
+}
+
+char *encode_params(game_params *params)
+{
+    char data[256];
+
+    sprintf(data, "%dx%d", params->w, params->h);
+
+    return dupstr(data);
+}
+
 config_item *game_configure(game_params *params)
 {
     config_item *ret;
index cce11d9..5b7b98e 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
+#include <ctype.h>
 #include <math.h>
 
 #include "puzzles.h"
@@ -92,6 +93,29 @@ game_params *dup_params(game_params *params)
     return ret;
 }
 
+game_params *decode_params(char const *string)
+{
+    game_params *ret = default_params();
+
+    ret->w = ret->h = atoi(string);
+    while (*string && isdigit(*string)) string++;
+    if (*string == 'x') {
+        string++;
+        ret->h = atoi(string);
+    }
+
+    return ret;
+}
+
+char *encode_params(game_params *params)
+{
+    char data[256];
+
+    sprintf(data, "%dx%d", params->w, params->h);
+
+    return dupstr(data);
+}
+
 config_item *game_configure(game_params *params)
 {
     config_item *ret;