puzzles: resync with upstream

This brings the code to upstream commit 3ece3d6 (I've made my own Rockbox-
specific changes on top of that).

Changes include using C99 `bool' throughout, and minor logic fixes for some
puzzles.

Change-Id: Ie823e73ae49a8ee1de411d6d406df2ba835af541
This commit is contained in:
Franklin Wei 2018-12-21 22:13:13 -05:00
parent f08d218e67
commit b3356e3aff
116 changed files with 8845 additions and 8423 deletions

View file

@ -59,8 +59,7 @@ struct game_state {
shared_state *shared;
borderflag *borders; /* length w*h */
unsigned int completed: 1;
unsigned int cheated: 1;
bool completed, cheated;
};
#define DEFAULT_PRESET 0
@ -75,15 +74,15 @@ static game_params *default_params(void)
return clone(&presets[DEFAULT_PRESET]);
}
static int game_fetch_preset(int i, char **name, game_params **params)
static bool game_fetch_preset(int i, char **name, game_params **params)
{
if (i < 0 || i >= lenof(presets)) return FALSE;
if (i < 0 || i >= lenof(presets)) return false;
*params = clone(&presets[i]);
*name = string(60, "%d x %d, regions of size %d",
presets[i].w, presets[i].h, presets[i].k);
return TRUE;
return true;
}
static void free_params(game_params *params)
@ -107,7 +106,7 @@ static void decode_params(game_params *params, char const *string)
if (*string == 'n') params->k = atoi(++string);
}
static char *encode_params(const game_params *params, int full)
static char *encode_params(const game_params *params, bool full)
{
return string(40, "%dx%dn%d", params->w, params->h, params->k);
}
@ -155,7 +154,7 @@ static game_params *custom_params(const config_item *cfg)
* +---+ the dominos is horizontal or vertical. +---+---+
*/
static const char *validate_params(const game_params *params, int full)
static const char *validate_params(const game_params *params, bool full)
{
int w = params->w, h = params->h, k = params->k, wh = w * h;
@ -268,7 +267,7 @@ static void connect(solver_ctx *ctx, int i, int j)
dsf_merge(ctx->dsf, i, j);
}
static int connected(solver_ctx *ctx, int i, int j, int dir)
static bool connected(solver_ctx *ctx, int i, int j, int dir)
{
if (j == COMPUTE_J) j = i + dx[dir] + ctx->params->w*dy[dir];
return dsf_canonify(ctx->dsf, i) == dsf_canonify(ctx->dsf, j);
@ -281,13 +280,13 @@ static void disconnect(solver_ctx *ctx, int i, int j, int dir)
ctx->borders[j] |= BORDER(FLIP(dir));
}
static int disconnected(solver_ctx *ctx, int i, int j, int dir)
static bool disconnected(solver_ctx *ctx, int i, int j, int dir)
{
assert (j == COMPUTE_J || j == i + dx[dir] + ctx->params->w*dy[dir]);
return ctx->borders[i] & BORDER(dir);
}
static int maybe(solver_ctx *ctx, int i, int j, int dir)
static bool maybe(solver_ctx *ctx, int i, int j, int dir)
{
assert (j == COMPUTE_J || j == i + dx[dir] + ctx->params->w*dy[dir]);
return !disconnected(ctx, i, j, dir) && !connected(ctx, i, j, dir);
@ -315,16 +314,16 @@ static void solver_connected_clues_versus_region_size(solver_ctx *ctx)
ctx->params->k != 2))
{
disconnect(ctx, i, j, dir);
/* changed = TRUE, but this is a one-shot... */
/* changed = true, but this is a one-shot... */
}
}
}
}
static int solver_number_exhausted(solver_ctx *ctx)
static bool solver_number_exhausted(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dir, off;
int changed = FALSE;
bool changed = false;
for (i = 0; i < wh; ++i) {
if (ctx->clues[i] == EMPTY) continue;
@ -334,7 +333,7 @@ static int solver_number_exhausted(solver_ctx *ctx)
int j = i + dx[dir] + w*dy[dir];
if (!maybe(ctx, i, j, dir)) continue;
connect(ctx, i, j);
changed = TRUE;
changed = true;
}
continue;
}
@ -350,17 +349,17 @@ static int solver_number_exhausted(solver_ctx *ctx)
int j = i + dx[dir] + w*dy[dir];
if (!maybe(ctx, i, j, dir)) continue;
disconnect(ctx, i, j, dir);
changed = TRUE;
changed = true;
}
}
return changed;
}
static int solver_not_too_big(solver_ctx *ctx)
static bool solver_not_too_big(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dir;
int changed = FALSE;
bool changed = false;
for (i = 0; i < wh; ++i) {
int size = dsf_size(ctx->dsf, i);
@ -369,17 +368,18 @@ static int solver_not_too_big(solver_ctx *ctx)
if (!maybe(ctx, i, j, dir)) continue;
if (size + dsf_size(ctx->dsf, j) <= ctx->params->k) continue;
disconnect(ctx, i, j, dir);
changed = TRUE;
changed = true;
}
}
return changed;
}
static int solver_not_too_small(solver_ctx *ctx)
static bool solver_not_too_small(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dir;
int *outs, k = ctx->params->k, ci, changed = FALSE;
int *outs, k = ctx->params->k, ci;
bool changed = false;
snewa(outs, wh);
setmem(outs, -1, wh);
@ -400,17 +400,17 @@ static int solver_not_too_small(solver_ctx *ctx)
if (i != dsf_canonify(ctx->dsf, i)) continue;
if (j < 0) continue;
connect(ctx, i, j); /* only one place for i to grow */
changed = TRUE;
changed = true;
}
sfree(outs);
return changed;
}
static int solver_no_dangling_edges(solver_ctx *ctx)
static bool solver_no_dangling_edges(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, r, c;
int changed = FALSE;
bool changed = false;
/* for each vertex */
for (r = 1; r < h; ++r)
@ -435,7 +435,7 @@ static int solver_no_dangling_edges(solver_ctx *ctx)
if (4 - noline == 1) {
assert (e != -1);
disconnect(ctx, e, COMPUTE_J, de);
changed = TRUE;
changed = true;
continue;
}
@ -447,21 +447,21 @@ static int solver_no_dangling_edges(solver_ctx *ctx)
if (ctx->borders[e] & BORDER(de)) {
if (!(ctx->borders[f] & BORDER(df))) {
disconnect(ctx, f, COMPUTE_J, df);
changed = TRUE;
changed = true;
}
} else if (ctx->borders[f] & BORDER(df)) {
disconnect(ctx, e, COMPUTE_J, de);
changed = TRUE;
changed = true;
}
}
return changed;
}
static int solver_equivalent_edges(solver_ctx *ctx)
static bool solver_equivalent_edges(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dirj;
int changed = FALSE;
bool changed = false;
/* if a square is adjacent to two connected squares, the two
* borders (i,j) and (i,k) are either both on or both off. */
@ -489,11 +489,11 @@ static int solver_equivalent_edges(solver_ctx *ctx)
if (n_on + 2 > ctx->clues[i]) {
connect(ctx, i, j);
connect(ctx, i, k);
changed = TRUE;
changed = true;
} else if (n_off + 2 > 4 - ctx->clues[i]) {
disconnect(ctx, i, j, dirj);
disconnect(ctx, i, k, dirk);
changed = TRUE;
changed = true;
}
}
}
@ -505,7 +505,7 @@ static int solver_equivalent_edges(solver_ctx *ctx)
#define UNVISITED 6
/* build connected components in `dsf', along the lines of `borders'. */
static void dfs_dsf(int i, int w, borderflag *border, int *dsf, int black)
static void dfs_dsf(int i, int w, borderflag *border, int *dsf, bool black)
{
int dir;
for (dir = 0; dir < 4; ++dir) {
@ -518,8 +518,8 @@ static void dfs_dsf(int i, int w, borderflag *border, int *dsf, int black)
}
}
static int is_solved(const game_params *params, clue *clues,
borderflag *border)
static bool is_solved(const game_params *params, clue *clues,
borderflag *border)
{
int w = params->w, h = params->h, wh = w*h, k = params->k;
int i, x, y;
@ -536,7 +536,7 @@ static int is_solved(const game_params *params, clue *clues,
* - the borders also satisfy the clue set
*/
for (i = 0; i < wh; ++i) {
if (dsf[i] == UNVISITED) dfs_dsf(i, params->w, border, dsf, TRUE);
if (dsf[i] == UNVISITED) dfs_dsf(i, params->w, border, dsf, true);
if (dsf_size(dsf, i) != k) goto error;
if (clues[i] == EMPTY) continue;
if (clues[i] != bitcount[border[i] & BORDER_MASK]) goto error;
@ -563,16 +563,17 @@ static int is_solved(const game_params *params, clue *clues,
}
sfree(dsf);
return TRUE;
return true;
error:
sfree(dsf);
return FALSE;
return false;
}
static int solver(const game_params *params, clue *clues, borderflag *borders)
static bool solver(const game_params *params, clue *clues, borderflag *borders)
{
int w = params->w, h = params->h, wh = w*h, changed;
int w = params->w, h = params->h, wh = w*h;
bool changed;
solver_ctx ctx;
ctx.params = params;
@ -582,7 +583,7 @@ static int solver(const game_params *params, clue *clues, borderflag *borders)
solver_connected_clues_versus_region_size(&ctx); /* idempotent */
do {
changed = FALSE;
changed = false;
changed |= solver_number_exhausted(&ctx);
changed |= solver_not_too_big(&ctx);
changed |= solver_not_too_small(&ctx);
@ -617,7 +618,7 @@ static void init_borders(int w, int h, borderflag *borders)
#define xshuffle(ptr, len, rs) shuffle((ptr), (len), sizeof (ptr)[0], (rs))
static char *new_game_desc(const game_params *params, random_state *rs,
char **aux, int interactive)
char **aux, bool interactive)
{
int w = params->w, h = params->h, wh = w*h, k = params->k;
@ -750,7 +751,7 @@ static game_state *new_game(midend *me, const game_params *params,
init_borders(w, h, state->borders);
state->completed = (params->k == wh);
state->cheated = FALSE;
state->cheated = false;
return state;
}
@ -819,9 +820,9 @@ static char *solve_game(const game_state *state, const game_state *currstate,
}
}
static int game_can_format_as_text_now(const game_params *params)
static bool game_can_format_as_text_now(const game_params *params)
{
return TRUE;
return true;
}
static char *game_text_format(const game_state *state)
@ -865,16 +866,15 @@ static char *game_text_format(const game_state *state)
struct game_ui {
int x, y;
unsigned int show: 1;
unsigned int fake_ctrl: 1;
unsigned int fake_shift: 1;
bool show;
bool fake_ctrl, fake_shift;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
ui->x = ui->y = 0;
ui->show = ui->fake_ctrl = ui->fake_shift = FALSE;
ui->show = ui->fake_ctrl = ui->fake_shift = false;
return ui;
}
@ -918,10 +918,10 @@ static char *interpret_move(const game_state *state, game_ui *ui,
const game_drawstate *ds, int x, int y, int button)
{
int w = state->shared->params.w, h = state->shared->params.h;
int control = (button & MOD_CTRL) | ui->fake_ctrl, shift = (button & MOD_SHFT) | ui->fake_shift;
bool control = (button & MOD_CTRL) | ui->fake_ctrl, shift = (button & MOD_SHFT) | ui->fake_shift;
/* reset */
ui->fake_ctrl = ui->fake_shift = FALSE;
ui->fake_ctrl = ui->fake_shift = false;
button &= ~MOD_MASK;
@ -950,7 +950,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
if (OUT_OF_BOUNDS(hx, hy, w, h)) return NULL;
ui->show = FALSE;
ui->show = false;
i = gy * w + gx;
switch ((button == RIGHT_BUTTON) |
@ -974,13 +974,13 @@ static char *interpret_move(const game_state *state, game_ui *ui,
}
if (IS_CURSOR_MOVE(button)) {
ui->show = TRUE;
ui->show = true;
if (control || shift) {
borderflag flag = 0, newflag;
int dir, i = ui->y * w + ui->x;
x = ui->x;
y = ui->y;
move_cursor(button, &x, &y, w, h, FALSE);
move_cursor(button, &x, &y, w, h, false);
if (OUT_OF_BOUNDS(x, y, w, h)) return NULL;
for (dir = 0; dir < 4; ++dir)
@ -1000,7 +1000,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
return string(80, "F%d,%d,%dF%d,%d,%d",
ui->x, ui->y, flag, x, y, newflag);
} else {
move_cursor(button, &ui->x, &ui->y, w, h, FALSE);
move_cursor(button, &ui->x, &ui->y, w, h, false);
return UI_UPDATE;
}
}
@ -1008,7 +1008,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
/* CURSOR_SELECT or CURSOR_SELECT2 tells us to toggle whether
* the button press should be interpreted as having CTRL or
* shift pressed along with it, respectively. */
ui->show = TRUE;
ui->show = true;
if(button == CURSOR_SELECT2)
ui->fake_shift = !ui->fake_shift;
else
@ -1031,7 +1031,7 @@ static game_state *execute_move(const game_state *state, const char *move)
ret->borders[i] =
(move[i] & BORDER_MASK) | DISABLED(~move[i] & BORDER_MASK);
if (i < wh || move[i]) return NULL; /* leaks `ret', then we die */
ret->cheated = ret->completed = TRUE;
ret->cheated = ret->completed = true;
return ret;
}
@ -1205,9 +1205,9 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
for (i = 0; i < wh; ++i) {
if (black_border_dsf[i] == UNVISITED)
dfs_dsf(i, w, state->borders, black_border_dsf, TRUE);
dfs_dsf(i, w, state->borders, black_border_dsf, true);
if (yellow_border_dsf[i] == UNVISITED)
dfs_dsf(i, w, state->borders, yellow_border_dsf, FALSE);
dfs_dsf(i, w, state->borders, yellow_border_dsf, false);
}
for (r = 0; r < h; ++r)
@ -1293,10 +1293,10 @@ static int game_status(const game_state *state)
return state->completed ? +1 : 0;
}
static int game_timing_state(const game_state *state, game_ui *ui)
static bool game_timing_state(const game_state *state, game_ui *ui)
{
assert (!"this shouldn't get called");
return 0; /* placate optimiser */
return false; /* placate optimiser */
}
static void game_print_size(const game_params *params, float *x, float *y)
@ -1310,7 +1310,7 @@ static void game_print_size(const game_params *params, float *x, float *y)
}
static void print_line(drawing *dr, int x1, int y1, int x2, int y2,
int colour, int full)
int colour, bool full)
{
if (!full) {
int i, subdivisions = 8;
@ -1377,15 +1377,15 @@ const struct game thegame = {
encode_params,
free_params,
dup_params,
TRUE, game_configure, custom_params,
true, game_configure, custom_params,
validate_params,
new_game_desc,
validate_desc,
new_game,
dup_game,
free_game,
TRUE, solve_game,
TRUE, game_can_format_as_text_now, game_text_format,
true, solve_game,
true, game_can_format_as_text_now, game_text_format,
new_ui,
free_ui,
encode_ui,
@ -1402,8 +1402,8 @@ const struct game thegame = {
game_anim_length,
game_flash_length,
game_status,
TRUE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
false, game_timing_state,
0, /* flags */
};