mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Produce shorter Filling descriptions by run-length encoding 0s.
This commit is contained in:

committed by
Simon Tatham

parent
f7eb186184
commit
3e2dc51db0
63
filling.c
63
filling.c
@ -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;
|
||||||
|
Reference in New Issue
Block a user