mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Introduce routines in each game module to encode a set of game
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]
This commit is contained in:
42
cube.c
42
cube.c
@ -6,6 +6,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -276,6 +277,37 @@ game_params *dup_params(game_params *params)
|
|||||||
return ret;
|
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,
|
static void enum_grid_squares(game_params *params,
|
||||||
void (*callback)(void *, struct grid_square *),
|
void (*callback)(void *, struct grid_square *),
|
||||||
void *ctx)
|
void *ctx)
|
||||||
@ -653,7 +685,7 @@ char *new_game_seed(game_params *params, random_state *rs)
|
|||||||
/*
|
/*
|
||||||
* Choose a non-blue square for the polyhedron.
|
* 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(data.gridptrs[0]);
|
||||||
sfree(flags);
|
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 */
|
/* NB if seed[j]=='\0' that will also be caught here, so we're safe */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seed[i] != ':')
|
if (seed[i] != ',')
|
||||||
return "Expected ':' after hex digits";
|
return "Expected ',' after hex digits";
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
do {
|
do {
|
||||||
if (seed[i] < '0' || seed[i] > '9')
|
if (seed[i] < '0' || seed[i] > '9')
|
||||||
return "Expected decimal integer after ':'";
|
return "Expected decimal integer after ','";
|
||||||
i++;
|
i++;
|
||||||
} while (seed[i]);
|
} while (seed[i]);
|
||||||
|
|
||||||
@ -883,7 +915,7 @@ game_state *new_game(game_params *params, char *seed)
|
|||||||
j = 8;
|
j = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p == ':')
|
if (*p == ',')
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
state->current = atoi(p);
|
state->current = atoi(p);
|
||||||
|
24
fifteen.c
24
fifteen.c
@ -6,6 +6,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -72,6 +73,29 @@ game_params *dup_params(game_params *params)
|
|||||||
return ret;
|
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 *game_configure(game_params *params)
|
||||||
{
|
{
|
||||||
config_item *ret;
|
config_item *ret;
|
||||||
|
40
midend.c
40
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)
|
config_item *midend_get_config(midend_data *me, int which, char **wintitle)
|
||||||
{
|
{
|
||||||
char *titlebuf;
|
char *titlebuf, *parstr;
|
||||||
config_item *ret;
|
config_item *ret;
|
||||||
|
|
||||||
titlebuf = snewn(40 + strlen(game_name), char);
|
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].type = C_STRING;
|
||||||
ret[0].name = "Game ID";
|
ret[0].name = "Game ID";
|
||||||
ret[0].ival = 0;
|
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].type = C_END;
|
||||||
ret[1].name = ret[1].sval = NULL;
|
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 *midend_set_config(midend_data *me, int which, config_item *cfg)
|
||||||
{
|
{
|
||||||
char *error;
|
char *error, *p;
|
||||||
game_params *params;
|
game_params *params;
|
||||||
|
|
||||||
switch (which) {
|
switch (which) {
|
||||||
@ -385,12 +393,34 @@ char *midend_set_config(midend_data *me, int which, config_item *cfg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CFG_SEED:
|
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)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
sfree(me->seed);
|
sfree(me->seed);
|
||||||
me->seed = dupstr(cfg[0].sval);
|
me->seed = dupstr(p);
|
||||||
me->fresh_seed = TRUE;
|
me->fresh_seed = TRUE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
39
net.c
39
net.c
@ -6,6 +6,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -183,6 +184,44 @@ game_params *dup_params(game_params *params)
|
|||||||
return ret;
|
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 *game_configure(game_params *params)
|
||||||
{
|
{
|
||||||
config_item *ret;
|
config_item *ret;
|
||||||
|
15
nullgame.c
15
nullgame.c
@ -15,6 +15,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -61,6 +62,20 @@ game_params *dup_params(game_params *params)
|
|||||||
return ret;
|
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)
|
config_item *game_configure(game_params *params)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -162,6 +162,8 @@ extern const char *const game_name;
|
|||||||
const int game_can_configure;
|
const int game_can_configure;
|
||||||
game_params *default_params(void);
|
game_params *default_params(void);
|
||||||
int game_fetch_preset(int i, char **name, game_params **params);
|
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);
|
void free_params(game_params *params);
|
||||||
game_params *dup_params(game_params *params);
|
game_params *dup_params(game_params *params);
|
||||||
config_item *game_configure(game_params *params);
|
config_item *game_configure(game_params *params);
|
||||||
|
24
rect.c
24
rect.c
@ -34,6 +34,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -129,6 +130,29 @@ game_params *dup_params(game_params *params)
|
|||||||
return ret;
|
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 *game_configure(game_params *params)
|
||||||
{
|
{
|
||||||
config_item *ret;
|
config_item *ret;
|
||||||
|
24
sixteen.c
24
sixteen.c
@ -8,6 +8,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -92,6 +93,29 @@ game_params *dup_params(game_params *params)
|
|||||||
return ret;
|
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 *game_configure(game_params *params)
|
||||||
{
|
{
|
||||||
config_item *ret;
|
config_item *ret;
|
||||||
|
Reference in New Issue
Block a user