chiark / gitweb /
Introduce routines in each game module to encode a set of game
authorSimon Tatham <anakin@pobox.com>
Wed, 19 May 2004 11:57:09 +0000 (11:57 +0000)
committerSimon Tatham <anakin@pobox.com>
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! :-)

[originally from svn r4231]

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 2ce7a4f286cea648f8dc8240a1871173f6e3997f..afd2ebd19d1e181f59f35d4ab51e39d0d7022706 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 78060f54a097c67024d594c7f8ac421b478581ea..2788604c79012d899940007726a2b14c728b5cb1 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 63ba193b29dc329efedb4dae33cfa6724ed3b068..6a9385631e30e3679111a74af61cb3d966d07ffe 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 d616d03cd75ee04cf0aeb741bb52876306a07a12..3c3f971e7ce03942e225eaedd01b654f31ef9ea6 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 32e6e2c7f75192252b36ee93b98eb5269c457d5f..67982b9119b4a7ed8f4d070426f4d48ab5875b15 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 46c0f15663dc75ea90f2098a13843853fdf1b1f7..37c190a0ac050326b93995bdc59f0927cc379e00 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 dcd8ef78076fcff76fb9fa919150db57df4a5760..9b7816c34a67189f74f88c477b242b6726e9c26b 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 cce11d9c9649ab38860de3dd65dd3c2f0c322c44..5b7b98e258f4c789daffb3f1f8d68374d5807d6e 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;