mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Implement selection of game seeds, by reusing the config box
mechanism I've just invented (the midend handles the standard game selection configuration). Each game is now required to validate its own seed data before attempting to base a game on it and potentially confusing itself. [originally from svn r4186]
This commit is contained in:
32
cube.c
32
cube.c
@ -285,8 +285,8 @@ static void enum_grid_squares(game_params *params,
|
|||||||
if (solid->order == 4) {
|
if (solid->order == 4) {
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
for (x = 0; x < params->d1; x++)
|
for (y = 0; y < params->d2; y++)
|
||||||
for (y = 0; y < params->d2; y++) {
|
for (x = 0; x < params->d1; x++) {
|
||||||
struct grid_square sq;
|
struct grid_square sq;
|
||||||
|
|
||||||
sq.x = (float)x;
|
sq.x = (float)x;
|
||||||
@ -809,6 +809,34 @@ static struct solid *transform_poly(const struct solid *solid, int flip,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *validate_seed(game_params *params, char *seed)
|
||||||
|
{
|
||||||
|
int area = grid_area(params->d1, params->d2, solids[params->solid]->order);
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
i = (area + 3) / 4;
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
int c = seed[j];
|
||||||
|
if (c >= '0' && c <= '9') continue;
|
||||||
|
if (c >= 'A' && c <= 'F') continue;
|
||||||
|
if (c >= 'a' && c <= 'f') continue;
|
||||||
|
return "Not enough hex digits at start of string";
|
||||||
|
/* NB if seed[j]=='\0' that will also be caught here, so we're safe */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seed[i] != ':')
|
||||||
|
return "Expected ':' after hex digits";
|
||||||
|
|
||||||
|
i++;
|
||||||
|
do {
|
||||||
|
if (seed[i] < '0' || seed[i] > '9')
|
||||||
|
return "Expected decimal integer after ':'";
|
||||||
|
i++;
|
||||||
|
} while (seed[i]);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
game_state *new_game(game_params *params, char *seed)
|
game_state *new_game(game_params *params, char *seed)
|
||||||
{
|
{
|
||||||
game_state *state = snew(game_state);
|
game_state *state = snew(game_state);
|
||||||
|
51
fifteen.c
51
fifteen.c
@ -246,6 +246,57 @@ char *new_game_seed(game_params *params)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *validate_seed(game_params *params, char *seed)
|
||||||
|
{
|
||||||
|
char *p, *err;
|
||||||
|
int i, area;
|
||||||
|
int *used;
|
||||||
|
|
||||||
|
area = params->w * params->h;
|
||||||
|
p = seed;
|
||||||
|
err = NULL;
|
||||||
|
|
||||||
|
used = snewn(area, int);
|
||||||
|
for (i = 0; i < area; i++)
|
||||||
|
used[i] = FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < area; i++) {
|
||||||
|
char *q = p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (*p < '0' || *p > '9') {
|
||||||
|
err = "Not enough numbers in string";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
while (*p >= '0' && *p <= '9')
|
||||||
|
p++;
|
||||||
|
if (i < area-1 && *p != ',') {
|
||||||
|
err = "Expected comma after number";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else if (i == area-1 && *p) {
|
||||||
|
err = "Excess junk at end of string";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
n = atoi(q);
|
||||||
|
if (n < 0 || n >= area) {
|
||||||
|
err = "Number out of range";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (used[n]) {
|
||||||
|
err = "Number used twice";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
used[n] = TRUE;
|
||||||
|
|
||||||
|
if (*p) p++; /* eat comma */
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
sfree(used);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
game_state *new_game(game_params *params, char *seed)
|
game_state *new_game(game_params *params, char *seed)
|
||||||
{
|
{
|
||||||
game_state *state = snew(game_state);
|
game_state *state = snew(game_state);
|
||||||
|
33
gtk.c
33
gtk.c
@ -66,7 +66,7 @@ struct frontend {
|
|||||||
struct font *fonts;
|
struct font *fonts;
|
||||||
int nfonts, fontsize;
|
int nfonts, fontsize;
|
||||||
config_item *cfg;
|
config_item *cfg;
|
||||||
int cfgret;
|
int cfg_which, cfgret;
|
||||||
GtkWidget *cfgbox;
|
GtkWidget *cfgbox;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -421,7 +421,7 @@ static void config_ok_button_clicked(GtkButton *button, gpointer data)
|
|||||||
frontend *fe = (frontend *)data;
|
frontend *fe = (frontend *)data;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
err = midend_set_config(fe->me, fe->cfg);
|
err = midend_set_config(fe->me, fe->cfg_which, fe->cfg);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
error_box(fe->cfgbox, err);
|
error_box(fe->cfgbox, err);
|
||||||
@ -461,17 +461,20 @@ static void droplist_sel(GtkMenuItem *item, gpointer data)
|
|||||||
"user-data"));
|
"user-data"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_config(frontend *fe)
|
static int get_config(frontend *fe, int which)
|
||||||
{
|
{
|
||||||
GtkWidget *w, *table;
|
GtkWidget *w, *table;
|
||||||
|
char *title;
|
||||||
config_item *i;
|
config_item *i;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
fe->cfg = midend_get_config(fe->me);
|
fe->cfg = midend_get_config(fe->me, which, &title);
|
||||||
|
fe->cfg_which = which;
|
||||||
fe->cfgret = FALSE;
|
fe->cfgret = FALSE;
|
||||||
|
|
||||||
fe->cfgbox = gtk_dialog_new();
|
fe->cfgbox = gtk_dialog_new();
|
||||||
gtk_window_set_title(GTK_WINDOW(fe->cfgbox), "Configure");
|
gtk_window_set_title(GTK_WINDOW(fe->cfgbox), title);
|
||||||
|
sfree(title);
|
||||||
|
|
||||||
w = gtk_button_new_with_label("OK");
|
w = gtk_button_new_with_label("OK");
|
||||||
gtk_box_pack_end(GTK_BOX(GTK_DIALOG(fe->cfgbox)->action_area),
|
gtk_box_pack_end(GTK_BOX(GTK_DIALOG(fe->cfgbox)->action_area),
|
||||||
@ -635,7 +638,7 @@ static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
|
|||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
midend_set_params(fe->me, params);
|
midend_set_params(fe->me, params);
|
||||||
midend_new_game(fe->me, NULL);
|
midend_new_game(fe->me);
|
||||||
midend_size(fe->me, &x, &y);
|
midend_size(fe->me, &x, &y);
|
||||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
||||||
fe->w = x;
|
fe->w = x;
|
||||||
@ -645,12 +648,14 @@ static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
|
|||||||
static void menu_config_event(GtkMenuItem *menuitem, gpointer data)
|
static void menu_config_event(GtkMenuItem *menuitem, gpointer data)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)data;
|
frontend *fe = (frontend *)data;
|
||||||
|
int which = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(menuitem),
|
||||||
|
"user-data"));
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
if (!get_config(fe))
|
if (!get_config(fe, which))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
midend_new_game(fe->me, NULL);
|
midend_new_game(fe->me);
|
||||||
midend_size(fe->me, &x, &y);
|
midend_size(fe->me, &x, &y);
|
||||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
||||||
fe->w = x;
|
fe->w = x;
|
||||||
@ -687,7 +692,7 @@ static frontend *new_window(void)
|
|||||||
fe = snew(frontend);
|
fe = snew(frontend);
|
||||||
|
|
||||||
fe->me = midend_new(fe);
|
fe->me = midend_new(fe);
|
||||||
midend_new_game(fe->me, NULL);
|
midend_new_game(fe->me);
|
||||||
|
|
||||||
fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
gtk_window_set_title(GTK_WINDOW(fe->window), game_name);
|
gtk_window_set_title(GTK_WINDOW(fe->window), game_name);
|
||||||
@ -714,6 +719,14 @@ static frontend *new_window(void)
|
|||||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "New", 'n');
|
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "New", 'n');
|
||||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Restart", 'r');
|
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Restart", 'r');
|
||||||
|
|
||||||
|
menuitem = gtk_menu_item_new_with_label("Specific...");
|
||||||
|
gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
|
||||||
|
GINT_TO_POINTER(CFG_SEED));
|
||||||
|
gtk_container_add(GTK_CONTAINER(menu), menuitem);
|
||||||
|
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
|
||||||
|
GTK_SIGNAL_FUNC(menu_config_event), fe);
|
||||||
|
gtk_widget_show(menuitem);
|
||||||
|
|
||||||
if ((n = midend_num_presets(fe->me)) > 0 || game_can_configure) {
|
if ((n = midend_num_presets(fe->me)) > 0 || game_can_configure) {
|
||||||
GtkWidget *submenu;
|
GtkWidget *submenu;
|
||||||
int i;
|
int i;
|
||||||
@ -741,6 +754,8 @@ static frontend *new_window(void)
|
|||||||
|
|
||||||
if (game_can_configure) {
|
if (game_can_configure) {
|
||||||
menuitem = gtk_menu_item_new_with_label("Custom...");
|
menuitem = gtk_menu_item_new_with_label("Custom...");
|
||||||
|
gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
|
||||||
|
GPOINTER_TO_INT(CFG_SETTINGS));
|
||||||
gtk_container_add(GTK_CONTAINER(submenu), menuitem);
|
gtk_container_add(GTK_CONTAINER(submenu), menuitem);
|
||||||
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
|
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
|
||||||
GTK_SIGNAL_FUNC(menu_config_event), fe);
|
GTK_SIGNAL_FUNC(menu_config_event), fe);
|
||||||
|
81
midend.c
81
midend.c
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "puzzles.h"
|
#include "puzzles.h"
|
||||||
@ -13,6 +14,7 @@
|
|||||||
struct midend_data {
|
struct midend_data {
|
||||||
frontend *frontend;
|
frontend *frontend;
|
||||||
char *seed;
|
char *seed;
|
||||||
|
int fresh_seed;
|
||||||
int nstates, statesize, statepos;
|
int nstates, statesize, statepos;
|
||||||
|
|
||||||
game_params **presets;
|
game_params **presets;
|
||||||
@ -43,6 +45,7 @@ midend_data *midend_new(frontend *frontend)
|
|||||||
me->states = NULL;
|
me->states = NULL;
|
||||||
me->params = default_params();
|
me->params = default_params();
|
||||||
me->seed = NULL;
|
me->seed = NULL;
|
||||||
|
me->fresh_seed = FALSE;
|
||||||
me->drawstate = NULL;
|
me->drawstate = NULL;
|
||||||
me->oldstate = NULL;
|
me->oldstate = NULL;
|
||||||
me->presets = NULL;
|
me->presets = NULL;
|
||||||
@ -73,7 +76,7 @@ void midend_set_params(midend_data *me, game_params *params)
|
|||||||
me->params = dup_params(params);
|
me->params = dup_params(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void midend_new_game(midend_data *me, char *seed)
|
void midend_new_game(midend_data *me)
|
||||||
{
|
{
|
||||||
while (me->nstates > 0)
|
while (me->nstates > 0)
|
||||||
free_game(me->states[--me->nstates]);
|
free_game(me->states[--me->nstates]);
|
||||||
@ -83,11 +86,11 @@ void midend_new_game(midend_data *me, char *seed)
|
|||||||
|
|
||||||
assert(me->nstates == 0);
|
assert(me->nstates == 0);
|
||||||
|
|
||||||
sfree(me->seed);
|
if (!me->fresh_seed) {
|
||||||
if (seed)
|
sfree(me->seed);
|
||||||
me->seed = dupstr(seed);
|
|
||||||
else
|
|
||||||
me->seed = new_game_seed(me->params);
|
me->seed = new_game_seed(me->params);
|
||||||
|
} else
|
||||||
|
me->fresh_seed = FALSE;
|
||||||
|
|
||||||
ensure(me);
|
ensure(me);
|
||||||
me->states[me->nstates++] = new_game(me->params, me->seed);
|
me->states[me->nstates++] = new_game(me->params, me->seed);
|
||||||
@ -156,7 +159,7 @@ int midend_process_key(midend_data *me, int x, int y, int button)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (button == 'n' || button == 'N' || button == '\x0E') {
|
if (button == 'n' || button == 'N' || button == '\x0E') {
|
||||||
midend_new_game(me, NULL);
|
midend_new_game(me);
|
||||||
midend_redraw(me);
|
midend_redraw(me);
|
||||||
return 1; /* never animate */
|
return 1; /* never animate */
|
||||||
} else if (button == 'r' || button == 'R') {
|
} else if (button == 'r' || button == 'R') {
|
||||||
@ -300,26 +303,70 @@ int midend_wants_statusbar(midend_data *me)
|
|||||||
return game_wants_statusbar();
|
return game_wants_statusbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
config_item *midend_get_config(midend_data *me)
|
config_item *midend_get_config(midend_data *me, int which, char **wintitle)
|
||||||
{
|
{
|
||||||
return game_configure(me->params);
|
char *titlebuf;
|
||||||
|
config_item *ret;
|
||||||
|
|
||||||
|
titlebuf = snewn(40 + strlen(game_name), char);
|
||||||
|
|
||||||
|
switch (which) {
|
||||||
|
case CFG_SETTINGS:
|
||||||
|
sprintf(titlebuf, "%s configuration", game_name);
|
||||||
|
*wintitle = dupstr(titlebuf);
|
||||||
|
return game_configure(me->params);
|
||||||
|
case CFG_SEED:
|
||||||
|
sprintf(titlebuf, "%s game selection", game_name);
|
||||||
|
*wintitle = dupstr(titlebuf);
|
||||||
|
|
||||||
|
ret = snewn(2, config_item);
|
||||||
|
|
||||||
|
ret[0].type = C_STRING;
|
||||||
|
ret[0].name = "Game ID";
|
||||||
|
ret[0].ival = 0;
|
||||||
|
ret[0].sval = dupstr(me->seed);
|
||||||
|
|
||||||
|
ret[1].type = C_END;
|
||||||
|
ret[1].name = ret[1].sval = NULL;
|
||||||
|
ret[1].ival = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!"We shouldn't be here");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *midend_set_config(midend_data *me, config_item *cfg)
|
char *midend_set_config(midend_data *me, int which, config_item *cfg)
|
||||||
{
|
{
|
||||||
char *error;
|
char *error;
|
||||||
game_params *params;
|
game_params *params;
|
||||||
|
|
||||||
params = custom_params(cfg);
|
switch (which) {
|
||||||
error = validate_params(params);
|
case CFG_SETTINGS:
|
||||||
|
params = custom_params(cfg);
|
||||||
|
error = validate_params(params);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
free_params(params);
|
free_params(params);
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_params(me->params);
|
||||||
|
me->params = params;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFG_SEED:
|
||||||
|
error = validate_seed(me->params, cfg[0].sval);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
sfree(me->seed);
|
||||||
|
me->seed = dupstr(cfg[0].sval);
|
||||||
|
me->fresh_seed = TRUE;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_params(me->params);
|
|
||||||
me->params = params;
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
9
net.c
9
net.c
@ -272,6 +272,15 @@ char *new_game_seed(game_params *params)
|
|||||||
return dupstr(buf);
|
return dupstr(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *validate_seed(game_params *params, char *seed)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Since any string at all will suffice to seed the RNG, there
|
||||||
|
* is no validation required.
|
||||||
|
*/
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
* Construct an initial game state, given a seed and parameters.
|
* Construct an initial game state, given a seed and parameters.
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,11 @@ char *new_game_seed(game_params *params)
|
|||||||
return dupstr("FIXME");
|
return dupstr("FIXME");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *validate_seed(game_params *params, char *seed)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
game_state *new_game(game_params *params, char *seed)
|
game_state *new_game(game_params *params, char *seed)
|
||||||
{
|
{
|
||||||
game_state *state = snew(game_state);
|
game_state *state = snew(game_state);
|
||||||
|
@ -107,7 +107,7 @@ midend_data *midend_new(frontend *fe);
|
|||||||
void midend_free(midend_data *me);
|
void midend_free(midend_data *me);
|
||||||
void midend_set_params(midend_data *me, game_params *params);
|
void midend_set_params(midend_data *me, game_params *params);
|
||||||
void midend_size(midend_data *me, int *x, int *y);
|
void midend_size(midend_data *me, int *x, int *y);
|
||||||
void midend_new_game(midend_data *me, char *seed);
|
void midend_new_game(midend_data *me);
|
||||||
void midend_restart_game(midend_data *me);
|
void midend_restart_game(midend_data *me);
|
||||||
int midend_process_key(midend_data *me, int x, int y, int button);
|
int midend_process_key(midend_data *me, int x, int y, int button);
|
||||||
void midend_redraw(midend_data *me);
|
void midend_redraw(midend_data *me);
|
||||||
@ -117,8 +117,9 @@ int midend_num_presets(midend_data *me);
|
|||||||
void midend_fetch_preset(midend_data *me, int n,
|
void midend_fetch_preset(midend_data *me, int n,
|
||||||
char **name, game_params **params);
|
char **name, game_params **params);
|
||||||
int midend_wants_statusbar(midend_data *me);
|
int midend_wants_statusbar(midend_data *me);
|
||||||
config_item *midend_get_config(midend_data *me);
|
enum { CFG_SETTINGS, CFG_SEED };
|
||||||
char *midend_set_config(midend_data *me, config_item *cfg);
|
config_item *midend_get_config(midend_data *me, int which, char **wintitle);
|
||||||
|
char *midend_set_config(midend_data *me, int which, config_item *cfg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* malloc.c
|
* malloc.c
|
||||||
@ -160,6 +161,7 @@ config_item *game_configure(game_params *params);
|
|||||||
game_params *custom_params(config_item *cfg);
|
game_params *custom_params(config_item *cfg);
|
||||||
char *validate_params(game_params *params);
|
char *validate_params(game_params *params);
|
||||||
char *new_game_seed(game_params *params);
|
char *new_game_seed(game_params *params);
|
||||||
|
char *validate_seed(game_params *params, char *seed);
|
||||||
game_state *new_game(game_params *params, char *seed);
|
game_state *new_game(game_params *params, char *seed);
|
||||||
game_state *dup_game(game_state *state);
|
game_state *dup_game(game_state *state);
|
||||||
void free_game(game_state *state);
|
void free_game(game_state *state);
|
||||||
|
52
sixteen.c
52
sixteen.c
@ -257,6 +257,58 @@ char *new_game_seed(game_params *params)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *validate_seed(game_params *params, char *seed)
|
||||||
|
{
|
||||||
|
char *p, *err;
|
||||||
|
int i, area;
|
||||||
|
int *used;
|
||||||
|
|
||||||
|
area = params->w * params->h;
|
||||||
|
p = seed;
|
||||||
|
err = NULL;
|
||||||
|
|
||||||
|
used = snewn(area, int);
|
||||||
|
for (i = 0; i < area; i++)
|
||||||
|
used[i] = FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < area; i++) {
|
||||||
|
char *q = p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (*p < '0' || *p > '9') {
|
||||||
|
err = "Not enough numbers in string";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
while (*p >= '0' && *p <= '9')
|
||||||
|
p++;
|
||||||
|
if (i < area-1 && *p != ',') {
|
||||||
|
err = "Expected comma after number";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else if (i == area-1 && *p) {
|
||||||
|
err = "Excess junk at end of string";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
n = atoi(q);
|
||||||
|
if (n < 1 || n > area) {
|
||||||
|
err = "Number out of range";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (used[n-1]) {
|
||||||
|
err = "Number used twice";
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
used[n-1] = TRUE;
|
||||||
|
|
||||||
|
if (*p) p++; /* eat comma */
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
sfree(used);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
game_state *new_game(game_params *params, char *seed)
|
game_state *new_game(game_params *params, char *seed)
|
||||||
{
|
{
|
||||||
game_state *state = snew(game_state);
|
game_state *state = snew(game_state);
|
||||||
|
25
windows.c
25
windows.c
@ -19,6 +19,7 @@
|
|||||||
#define IDM_REDO 0x0040
|
#define IDM_REDO 0x0040
|
||||||
#define IDM_QUIT 0x0050
|
#define IDM_QUIT 0x0050
|
||||||
#define IDM_CONFIG 0x0060
|
#define IDM_CONFIG 0x0060
|
||||||
|
#define IDM_SEED 0x0070
|
||||||
#define IDM_PRESETS 0x0100
|
#define IDM_PRESETS 0x0100
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -93,7 +94,7 @@ struct frontend {
|
|||||||
int nfonts, fontsize;
|
int nfonts, fontsize;
|
||||||
config_item *cfg;
|
config_item *cfg;
|
||||||
struct cfg_aux *cfgaux;
|
struct cfg_aux *cfgaux;
|
||||||
int cfg_done;
|
int cfg_which, cfg_done;
|
||||||
HFONT cfgfont;
|
HFONT cfgfont;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -314,7 +315,7 @@ static frontend *new_window(HINSTANCE inst)
|
|||||||
fe = snew(frontend);
|
fe = snew(frontend);
|
||||||
fe->me = midend_new(fe);
|
fe->me = midend_new(fe);
|
||||||
fe->inst = inst;
|
fe->inst = inst;
|
||||||
midend_new_game(fe->me, NULL);
|
midend_new_game(fe->me);
|
||||||
midend_size(fe->me, &x, &y);
|
midend_size(fe->me, &x, &y);
|
||||||
|
|
||||||
fe->timer = 0;
|
fe->timer = 0;
|
||||||
@ -359,6 +360,7 @@ static frontend *new_window(HINSTANCE inst)
|
|||||||
AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "Game");
|
AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "Game");
|
||||||
AppendMenu(menu, MF_ENABLED, IDM_NEW, "New");
|
AppendMenu(menu, MF_ENABLED, IDM_NEW, "New");
|
||||||
AppendMenu(menu, MF_ENABLED, IDM_RESTART, "Restart");
|
AppendMenu(menu, MF_ENABLED, IDM_RESTART, "Restart");
|
||||||
|
AppendMenu(menu, MF_ENABLED, IDM_SEED, "Specific...");
|
||||||
|
|
||||||
if ((fe->npresets = midend_num_presets(fe->me)) > 0 ||
|
if ((fe->npresets = midend_num_presets(fe->me)) > 0 ||
|
||||||
game_can_configure) {
|
game_can_configure) {
|
||||||
@ -443,7 +445,7 @@ static int CALLBACK ConfigDlgProc(HWND hwnd, UINT msg,
|
|||||||
HIWORD(wParam) == BN_DOUBLECLICKED) &&
|
HIWORD(wParam) == BN_DOUBLECLICKED) &&
|
||||||
(LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) {
|
(LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) {
|
||||||
if (LOWORD(wParam) == IDOK) {
|
if (LOWORD(wParam) == IDOK) {
|
||||||
char *err = midend_set_config(fe->me, fe->cfg);
|
char *err = midend_set_config(fe->me, fe->cfg_which, fe->cfg);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
MessageBox(hwnd, err, "Validation error",
|
MessageBox(hwnd, err, "Validation error",
|
||||||
@ -505,10 +507,11 @@ HWND mkctrl(frontend *fe, int x1, int x2, int y1, int y2,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_config(frontend *fe)
|
static int get_config(frontend *fe, int which)
|
||||||
{
|
{
|
||||||
config_item *i;
|
config_item *i;
|
||||||
struct cfg_aux *j;
|
struct cfg_aux *j;
|
||||||
|
char *title;
|
||||||
WNDCLASS wc;
|
WNDCLASS wc;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
TEXTMETRIC tm;
|
TEXTMETRIC tm;
|
||||||
@ -553,7 +556,8 @@ static int get_config(frontend *fe)
|
|||||||
height = width = 30;
|
height = width = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
fe->cfg = midend_get_config(fe->me);
|
fe->cfg = midend_get_config(fe->me, which, &title);
|
||||||
|
fe->cfg_which = which;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out the layout of the config box by measuring the
|
* Figure out the layout of the config box by measuring the
|
||||||
@ -627,12 +631,13 @@ static int get_config(frontend *fe)
|
|||||||
r.right += r.left;
|
r.right += r.left;
|
||||||
r.bottom += r.top;
|
r.bottom += r.top;
|
||||||
|
|
||||||
fe->cfgbox = CreateWindowEx(0, wc.lpszClassName, "Configuration",
|
fe->cfgbox = CreateWindowEx(0, wc.lpszClassName, title,
|
||||||
DS_MODALFRAME | WS_POPUP | WS_VISIBLE |
|
DS_MODALFRAME | WS_POPUP | WS_VISIBLE |
|
||||||
WS_CAPTION | WS_SYSMENU,
|
WS_CAPTION | WS_SYSMENU,
|
||||||
r.left, r.top,
|
r.left, r.top,
|
||||||
r.right-r.left, r.bottom-r.top,
|
r.right-r.left, r.bottom-r.top,
|
||||||
fe->hwnd, NULL, fe->inst, NULL);
|
fe->hwnd, NULL, fe->inst, NULL);
|
||||||
|
sfree(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMessage(fe->cfgbox, WM_SETFONT, (WPARAM)fe->cfgfont, FALSE);
|
SendMessage(fe->cfgbox, WM_SETFONT, (WPARAM)fe->cfgfont, FALSE);
|
||||||
@ -747,7 +752,7 @@ static void new_game_type(frontend *fe)
|
|||||||
HDC hdc;
|
HDC hdc;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
midend_new_game(fe->me, NULL);
|
midend_new_game(fe->me);
|
||||||
midend_size(fe->me, &x, &y);
|
midend_size(fe->me, &x, &y);
|
||||||
|
|
||||||
r.left = r.top = 0;
|
r.left = r.top = 0;
|
||||||
@ -812,7 +817,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
|||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
break;
|
break;
|
||||||
case IDM_CONFIG:
|
case IDM_CONFIG:
|
||||||
if (get_config(fe))
|
if (get_config(fe, CFG_SETTINGS))
|
||||||
|
new_game_type(fe);
|
||||||
|
break;
|
||||||
|
case IDM_SEED:
|
||||||
|
if (get_config(fe, CFG_SEED))
|
||||||
new_game_type(fe);
|
new_game_type(fe);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Reference in New Issue
Block a user