Produce shorter Filling descriptions by run-length encoding 0s.

This commit is contained in:
Jonas Kölker
2015-10-07 22:52:54 +02:00
committed by Simon Tatham
parent f7eb186184
commit 3e2dc51db0

View File

@ -898,44 +898,64 @@ static void minimize_clue_set(int *board, int w, int h, random_state *rs)
sfree(shuf); sfree(shuf);
} }
static int encode_run(char *buffer, int run)
{
int i = 0;
for (; run > 26; run -= 26)
buffer[i++] = 'z';
if (run)
buffer[i++] = 'a' - 1 + run;
return i;
}
static char *new_game_desc(const game_params *params, random_state *rs, static char *new_game_desc(const game_params *params, random_state *rs,
char **aux, int interactive) char **aux, int interactive)
{ {
const int w = params->w, h = params->h, sz = w * h; const int w = params->w, h = params->h, sz = w * h;
int *board = snewn(sz, int), i; int *board = snewn(sz, int), i, j, run;
char *game_description = snewn(sz + 1, char); char *description = snewn(sz + 1, char);
make_board(board, w, h, rs); make_board(board, w, h, rs);
minimize_clue_set(board, w, h, rs); minimize_clue_set(board, w, h, rs);
for (i = 0; i < sz; ++i) { for (run = j = i = 0; i < sz; ++i) {
assert(board[i] >= 0); assert(board[i] >= 0);
assert(board[i] < 10); assert(board[i] < 10);
game_description[i] = board[i] + '0'; if (board[i] == 0) {
++run;
} else {
j += encode_run(description + j, run);
run = 0;
description[j++] = board[i] + '0';
} }
game_description[sz] = '\0'; }
j += encode_run(description + j, run);
description[j++] = '\0';
sfree(board); sfree(board);
return game_description; return sresize(description, j, char);
} }
static char *validate_desc(const game_params *params, const char *desc) static char *validate_desc(const game_params *params, const char *desc)
{ {
int i;
const int sz = params->w * params->h; const int sz = params->w * params->h;
const char m = '0' + max(max(params->w, params->h), 3); const char m = '0' + max(max(params->w, params->h), 3);
int area;
printv("desc = '%s'; sz = %d\n", desc, sz); for (area = 0; *desc; ++desc) {
if (*desc >= 'a' && *desc <= 'z') area += *desc - 'a' + 1;
for (i = 0; desc[i] && i < sz; ++i) else if (*desc >= '0' && *desc <= m) ++area;
if (!isdigit((unsigned char) *desc)) else {
return "non-digit in string"; static char s[] = "Invalid character '%""' in game description";
else if (desc[i] > m) int n = sprintf(s, "Invalid character '%1c' in game description",
return "too large digit in string"; *desc);
if (desc[i]) return "string too long"; assert(n + 1 <= lenof(s)); /* +1 for the terminating NUL */
else if (i < sz) return "string too short"; return s;
return NULL; }
if (area > sz) return "Too much data to fit in grid";
}
return (area < sz) ? "Not enough data to fill grid" : NULL;
} }
static game_state *new_game(midend *me, const game_params *params, static game_state *new_game(midend *me, const game_params *params,
@ -950,7 +970,14 @@ static game_state *new_game(midend *me, const game_params *params,
state->shared->refcnt = 1; state->shared->refcnt = 1;
state->shared->params = *params; /* struct copy */ state->shared->params = *params; /* struct copy */
state->shared->clues = snewn(sz, int); state->shared->clues = snewn(sz, int);
for (i = 0; i < sz; ++i) state->shared->clues[i] = desc[i] - '0';
for (i = 0; *desc; ++desc) {
if (*desc >= 'a' && *desc <= 'z') {
int j = *desc - 'a' + 1;
assert(i + j <= sz);
for (; j; --j) state->shared->clues[i++] = 0;
} else state->shared->clues[i++] = *desc - '0';
}
state->board = memdup(state->shared->clues, sz, sizeof (int)); state->board = memdup(state->shared->clues, sz, sizeof (int));
return state; return state;