* up on compactness and just bite the bullet and have the
* target area right outside the main wall, but mostly I
* think it's OK.
- * * but adjust the presets, because 8x6 is _slow_ to
- * generate.
- * * also, introduce a difficulty scheme, in the form of
- * limiting the minimum move count. This is obviously
- * sensible, because it also speeds up generation since the
- * solver can bomb out once it hits that ceiling!
- * + I was going to say I'd need to work out a minimum move
- * count for each grid size, but actually I think not: if
- * you ask for too few moves, it just has to remove still
- * more singletons, until at move count 1 you end up with
- * nothing in your way at all and it SERVES YOU RIGHT!
+ * * the move limit tends to make the game _slower_ to
+ * generate, which is odd. Perhaps investigate why.
*
* - Improve the graphics.
* * All the colours are a bit wishy-washy. _Some_ dark
struct game_params {
int w, h;
+ int maxmoves;
};
struct game_immutable_state {
{
game_params *ret = snew(game_params);
- ret->w = 8;
+ ret->w = 7;
ret->h = 6;
+ ret->maxmoves = 40;
return ret;
}
static const struct game_params slide_presets[] = {
- {6, 5},
- {7, 5},
- {7, 6},
- {8, 6},
+ {7, 6, 25},
+ {7, 6, -1},
+ {8, 6, -1},
};
static int game_fetch_preset(int i, char **name, game_params **params)
*ret = slide_presets[i];
sprintf(str, "%dx%d", ret->w, ret->h);
+ if (ret->maxmoves >= 0)
+ sprintf(str + strlen(str), ", max %d moves", ret->maxmoves);
+ else
+ sprintf(str + strlen(str), ", no move limit");
*name = dupstr(str);
*params = ret;
if (*string == 'x') {
string++;
params->h = atoi(string);
+ while (*string && isdigit((unsigned char)*string)) string++;
+ }
+ if (*string == 'm') {
+ string++;
+ params->maxmoves = atoi(string);
+ while (*string && isdigit((unsigned char)*string)) string++;
+ } else if (*string == 'u') {
+ string++;
+ params->maxmoves = -1;
}
}
char data[256];
sprintf(data, "%dx%d", params->w, params->h);
+ if (params->maxmoves >= 0)
+ sprintf(data + strlen(data), "m%d", params->maxmoves);
+ else
+ sprintf(data + strlen(data), "u");
return dupstr(data);
}
config_item *ret;
char buf[80];
- ret = snewn(3, config_item);
+ ret = snewn(4, config_item);
ret[0].name = "Width";
ret[0].type = C_STRING;
ret[1].sval = dupstr(buf);
ret[1].ival = 0;
- ret[2].name = NULL;
- ret[2].type = C_END;
- ret[2].sval = NULL;
+ ret[2].name = "Solution length limit";
+ ret[2].type = C_STRING;
+ sprintf(buf, "%d", params->maxmoves);
+ ret[2].sval = dupstr(buf);
ret[2].ival = 0;
+ ret[3].name = NULL;
+ ret[3].type = C_END;
+ ret[3].sval = NULL;
+ ret[3].ival = 0;
+
return ret;
}
ret->w = atoi(cfg[0].sval);
ret->h = atoi(cfg[1].sval);
+ ret->maxmoves = atoi(cfg[2].sval);
return ret;
}
* as-yet-unprovided parameter.
*/
static int solve_board(int w, int h, unsigned char *board,
- unsigned char *forcefield, int tx, int ty)
+ unsigned char *forcefield, int tx, int ty,
+ int movelimit)
{
int wh = w*h;
struct board *b, *b2, *b3;
while ((b = delpos234(queue, 0)) != NULL) {
qlen--;
+ if (movelimit >= 0 && b->dist >= movelimit) {
+ /*
+ * The problem is not soluble in under `movelimit'
+ * moves, so we can quit right now.
+ */
+ b2 = NULL;
+ goto done;
+ }
if (b->dist != lastdist) {
#ifdef SOLVER_DIAGNOSTICS
printf("dist %d (%d)\n", b->dist, count234(sorted));
static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
random_state *rs, unsigned char **rboard,
- unsigned char **rforcefield)
+ unsigned char **rforcefield, int movelimit)
{
int wh = w*h;
unsigned char *board, *board2, *forcefield;
* See if the board is already soluble.
*/
if ((moves = solve_board(w, h, board, forcefield,
- tx, ty)) >= 0)
+ tx, ty, movelimit)) >= 0)
goto soluble;
/*
c1 = dsf_canonify(dsf, p1);
c2 = dsf_canonify(dsf, p2);
if (tried_merge[c1 * wh + c2])
-{printf("aha\n");
continue;
-}
/*
* In order to be mergeable, these two squares must each
} while (p2 < wh && board[p2] != DIST(p2-i));
}
}
- j = solve_board(w, h, board, forcefield, tx, ty);
+ j = solve_board(w, h, board, forcefield, tx, ty, movelimit);
if (j < 0) {
/*
* Didn't work. Revert the merge.
int i;
generate_board(params->w, params->h, &tx, &ty, &minmoves, rs,
- &board, &forcefield);
+ &board, &forcefield, params->maxmoves);
#ifdef GENERATOR_DIAGNOSTICS
{
char *t = board_text_format(params->w, params->h, board);