From 09aa8de52cb962f1ceebfb1fd44f2c54a924fc5c Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Mon, 22 Jul 2024 21:43:25 -0400 Subject: puzzles: resync with upstream This brings the puzzles source in sync with Simon's branch, commit fd304c5 (from March 2024), with some added Rockbox-specific compatibility changes: https://www.franklinwei.com/git/puzzles/commit/?h=rockbox-devel&id=516830d9d76bdfe64fe5ccf2a9b59c33f5c7c078 There are quite a lot of backend changes, including a new "Mosaic" puzzle. In addition, some new frontend changes were necessary: - New "Preferences" menu to access the user preferences system. - Enabled spacebar input for several games. Change-Id: I94c7df674089c92f32d5f07025f6a1059068af1e --- apps/plugins/puzzles/src/magnets.c | 125 +++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 47 deletions(-) (limited to 'apps/plugins/puzzles/src/magnets.c') diff --git a/apps/plugins/puzzles/src/magnets.c b/apps/plugins/puzzles/src/magnets.c index edbb8490ad..7cb5fbc919 100644 --- a/apps/plugins/puzzles/src/magnets.c +++ b/apps/plugins/puzzles/src/magnets.c @@ -36,12 +36,17 @@ #include #include #include -#include +#include +#ifdef NO_TGMATH_H +# include +#else +# include +#endif #include "puzzles.h" #ifdef STANDALONE_SOLVER -bool verbose = 0; +static bool verbose = false; #endif enum { @@ -230,8 +235,17 @@ static game_params *custom_params(const config_item *cfg) static const char *validate_params(const game_params *params, bool full) { - if (params->w < 2) return "Width must be at least one"; - if (params->h < 2) return "Height must be at least one"; + if (params->w < 2) return "Width must be at least two"; + if (params->h < 2) return "Height must be at least two"; + if (params->w > INT_MAX / params->h) + return "Width times height must not be unreasonably large"; + if (params->diff >= DIFF_TRICKY) { + if (params->w < 5 && params->h < 5) + return "Either width or height must be at least five for Tricky"; + } else { + if (params->w < 3 && params->h < 3) + return "Either width or height must be at least three"; + } if (params->diff < 0 || params->diff >= DIFFCOUNT) return "Unknown difficulty level"; @@ -510,7 +524,9 @@ nextchar: * (i.e. each end points to the other) */ for (idx = 0; idx < state->wh; idx++) { if (state->common->dominoes[idx] < 0 || - state->common->dominoes[idx] > state->wh || + state->common->dominoes[idx] >= state->wh || + (state->common->dominoes[idx] % state->w != idx % state->w && + state->common->dominoes[idx] / state->w != idx / state->w) || state->common->dominoes[state->common->dominoes[idx]] != idx) { *prob = "Domino descriptions inconsistent"; goto done; @@ -541,7 +557,7 @@ static const char *validate_desc(const game_params *params, const char *desc) { const char *prob; game_state *st = new_game_int(params, desc, &prob); - if (!st) return (char*)prob; + if (!st) return prob; free_game(st); return NULL; } @@ -1574,6 +1590,7 @@ static int lay_dominoes(game_state *state, random_state *rs, int *scratch) } debug(("Laid %d dominoes, total %d dominoes.\n", nlaid, state->wh/2)); + (void)nlaid; game_debug(state, "Final layout"); return ret; } @@ -1720,7 +1737,7 @@ static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->cur_x = ui->cur_y = 0; - ui->cur_visible = false; + ui->cur_visible = getenv_bool("PUZZLES_SHOW_CURSOR", false); return ui; } @@ -1729,15 +1746,6 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(const game_ui *ui) -{ - return NULL; -} - -static void decode_ui(game_ui *ui, const char *encoding) -{ -} - static void game_changed_state(game_ui *ui, const game_state *oldstate, const game_state *newstate) { @@ -1745,6 +1753,36 @@ static void game_changed_state(game_ui *ui, const game_state *oldstate, ui->cur_visible = false; } +static const char *current_key_label(const game_ui *ui, + const game_state *state, int button) +{ + int idx; + + if (IS_CURSOR_SELECT(button)) { + if (!ui->cur_visible) return ""; + idx = ui->cur_y * state->w + ui->cur_x; + if (button == CURSOR_SELECT) { + if (state->grid[idx] == NEUTRAL && state->flags[idx] & GS_SET) + return ""; + switch (state->grid[idx]) { + case EMPTY: return "+"; + case POSITIVE: return "-"; + case NEGATIVE: return "Clear"; + } + } + if (button == CURSOR_SELECT2) { + if (state->grid[idx] != NEUTRAL) return ""; + if (state->flags[idx] & GS_SET) /* neutral */ + return "?"; + if (state->flags[idx] & GS_NOTNEUTRAL) /* !neutral */ + return "Clear"; + else + return "X"; + } + } + return ""; +} + struct game_drawstate { int tilesize; bool started, solved; @@ -1805,14 +1843,13 @@ static char *interpret_move(const game_state *state, game_ui *ui, char *nullret = NULL, buf[80], movech; enum { CYCLE_MAGNET, CYCLE_NEUTRAL } action; - if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false); - ui->cur_visible = true; - return UI_UPDATE; - } else if (IS_CURSOR_SELECT(button)) { + if (IS_CURSOR_MOVE(button)) + return move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, + false, &ui->cur_visible); + else if (IS_CURSOR_SELECT(button)) { if (!ui->cur_visible) { ui->cur_visible = true; - return UI_UPDATE; + return MOVE_UI_UPDATE; } action = (button == CURSOR_SELECT) ? CYCLE_MAGNET : CYCLE_NEUTRAL; gx = ui->cur_x; @@ -1821,7 +1858,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, (button == LEFT_BUTTON || button == RIGHT_BUTTON)) { if (ui->cur_visible) { ui->cur_visible = false; - nullret = UI_UPDATE; + nullret = MOVE_UI_UPDATE; } action = (button == LEFT_BUTTON) ? CYCLE_MAGNET : CYCLE_NEUTRAL; } else if (button == LEFT_BUTTON && is_clue(state, gx, gy)) { @@ -1928,7 +1965,7 @@ badmove: */ static void game_compute_size(const game_params *params, int tilesize, - int *x, int *y) + const game_ui *ui, int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2205,12 +2242,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, flash = (int)(flashtime * 5 / FLASH_TIME) % 2; if (!ds->started) { - /* draw background, corner +-. */ - draw_rect(dr, 0, 0, - TILE_SIZE * (w+2) + 2 * BORDER, - TILE_SIZE * (h+2) + 2 * BORDER, - COL_BACKGROUND); - + /* draw corner +-. */ draw_sym(dr, ds, -1, -1, POSITIVE, COL_TEXT); draw_sym(dr, ds, state->w, state->h, NEGATIVE, COL_TEXT); @@ -2309,24 +2341,21 @@ static int game_status(const game_state *state) return state->completed ? +1 : 0; } -static bool game_timing_state(const game_state *state, game_ui *ui) -{ - return true; -} - -static void game_print_size(const game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, const game_ui *ui, + float *x, float *y) { int pw, ph; /* * I'll use 6mm squares by default. */ - game_compute_size(params, 600, &pw, &ph); + game_compute_size(params, 600, ui, &pw, &ph); *x = pw / 100.0F; *y = ph / 100.0F; } -static void game_print(drawing *dr, const game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, const game_ui *ui, + int tilesize) { int w = state->w, h = state->h; int ink = print_mono_colour(dr, 0); @@ -2430,12 +2459,14 @@ const struct game thegame = { free_game, true, solve_game, true, game_can_format_as_text_now, game_text_format, + NULL, NULL, /* get_prefs, set_prefs */ new_ui, free_ui, - encode_ui, - decode_ui, + NULL, /* encode_ui */ + NULL, /* decode_ui */ NULL, /* game_request_keys */ game_changed_state, + current_key_label, interpret_move, execute_move, PREFERRED_TILE_SIZE, game_compute_size, game_set_size, @@ -2449,7 +2480,7 @@ const struct game thegame = { game_status, true, false, game_print_size, game_print, false, /* wants_statusbar */ - false, game_timing_state, + false, NULL, /* timing_state */ REQUIRE_RBUTTON, /* flags */ }; @@ -2458,14 +2489,14 @@ const struct game thegame = { #include #include -const char *quis = NULL; -bool csv = false; +static const char *quis = NULL; +static bool csv = false; -void usage(FILE *out) { +static void usage(FILE *out) { fprintf(out, "usage: %s [-v] [--print] |\n", quis); } -void doprint(game_state *state) +static void doprint(game_state *state) { char *fmt = game_text_format(state); printf("%s", fmt); @@ -2559,7 +2590,7 @@ static void start_soak(game_params *p, random_state *rs) sfree(aux); } -int main(int argc, const char *argv[]) +int main(int argc, char *argv[]) { bool print = false, soak = false, solved = false; int ret; @@ -2608,7 +2639,7 @@ int main(int argc, const char *argv[]) decode_params(p, id); err = validate_params(p, true); if (err) { - fprintf(stderr, "%s: %s", argv[0], err); + fprintf(stderr, "%s: %s\n", argv[0], err); goto done; } -- cgit v1.2.3