diff options
| author | Franklin Wei <git@fwei.tk> | 2018-04-17 18:18:40 -0400 |
|---|---|---|
| committer | Franklin Wei <git@fwei.tk> | 2018-04-17 18:20:12 -0400 |
| commit | 6dc9d1d7309613fdc0518c03b2cdf3253d4c52fd (patch) | |
| tree | f6c9abf4a05f640134aa3d248a9498a06f596712 /apps/plugins/puzzles/src | |
| parent | 7a12e796a62b916dae5de1b2986e8cb11ac5be4c (diff) | |
| download | rockbox-6dc9d1d7309613fdc0518c03b2cdf3253d4c52fd.zip rockbox-6dc9d1d7309613fdc0518c03b2cdf3253d4c52fd.tar.gz rockbox-6dc9d1d7309613fdc0518c03b2cdf3253d4c52fd.tar.bz2 rockbox-6dc9d1d7309613fdc0518c03b2cdf3253d4c52fd.tar.xz | |
puzzles: enable all the remaining games
They all work now :). I merged in part of Chris Boyle's Android port of
Puzzles to give the front end a way to know what keys the back end needs.
This also re-syncs to the latest upstream sources.
Change-Id: Ie0409bbb32f617ae5abf4f81be3b45d1552db9bb
Diffstat (limited to 'apps/plugins/puzzles/src')
43 files changed, 290 insertions, 48 deletions
diff --git a/apps/plugins/puzzles/src/blackbox.c b/apps/plugins/puzzles/src/blackbox.c index ffc7f7c..caaa9eb 100644 --- a/apps/plugins/puzzles/src/blackbox.c +++ b/apps/plugins/puzzles/src/blackbox.c @@ -1521,6 +1521,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/bridges.c b/apps/plugins/puzzles/src/bridges.c index 0a326f2..098fea2 100644 --- a/apps/plugins/puzzles/src/bridges.c +++ b/apps/plugins/puzzles/src/bridges.c @@ -3238,6 +3238,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/cube.c b/apps/plugins/puzzles/src/cube.c index 2a79a81..7491565 100644 --- a/apps/plugins/puzzles/src/cube.c +++ b/apps/plugins/puzzles/src/cube.c @@ -1751,6 +1751,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/dominosa.c b/apps/plugins/puzzles/src/dominosa.c index a072ac6..73b744d 100644 --- a/apps/plugins/puzzles/src/dominosa.c +++ b/apps/plugins/puzzles/src/dominosa.c @@ -1723,6 +1723,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/fifteen.c b/apps/plugins/puzzles/src/fifteen.c index f749e96..35bcb32 100644 --- a/apps/plugins/puzzles/src/fifteen.c +++ b/apps/plugins/puzzles/src/fifteen.c @@ -1103,6 +1103,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/filling.c b/apps/plugins/puzzles/src/filling.c index 231de4c..c331dac 100644 --- a/apps/plugins/puzzles/src/filling.c +++ b/apps/plugins/puzzles/src/filling.c @@ -1287,6 +1287,11 @@ static const char *validate_desc(const game_params *params, const char *desc) return (area < sz) ? "Not enough data to fill grid" : NULL; } +static char *game_request_keys(const game_params *params) +{ + return dupstr("1234567890\b"); +} + static game_state *new_game(midend *me, const game_params *params, const char *desc) { @@ -2125,6 +2130,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + game_request_keys, game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/flip.c b/apps/plugins/puzzles/src/flip.c index 9e5716a..481c4b5 100644 --- a/apps/plugins/puzzles/src/flip.c +++ b/apps/plugins/puzzles/src/flip.c @@ -1327,6 +1327,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/flood.c b/apps/plugins/puzzles/src/flood.c index 854469a..840ff64 100644 --- a/apps/plugins/puzzles/src/flood.c +++ b/apps/plugins/puzzles/src/flood.c @@ -1350,6 +1350,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/galaxies.c b/apps/plugins/puzzles/src/galaxies.c index 5d7dbdf..11efd34 100644 --- a/apps/plugins/puzzles/src/galaxies.c +++ b/apps/plugins/puzzles/src/galaxies.c @@ -3652,6 +3652,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/guess.c b/apps/plugins/puzzles/src/guess.c index a14f3bd..98019d2 100644 --- a/apps/plugins/puzzles/src/guess.c +++ b/apps/plugins/puzzles/src/guess.c @@ -1493,6 +1493,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/inertia.c b/apps/plugins/puzzles/src/inertia.c index 22cf235..8206d00 100644 --- a/apps/plugins/puzzles/src/inertia.c +++ b/apps/plugins/puzzles/src/inertia.c @@ -2234,6 +2234,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/keen.c b/apps/plugins/puzzles/src/keen.c index ec7af12..f3142a0 100644 --- a/apps/plugins/puzzles/src/keen.c +++ b/apps/plugins/puzzles/src/keen.c @@ -1251,6 +1251,20 @@ static const char *validate_desc(const game_params *params, const char *desc) return NULL; } +static char *game_request_keys(const game_params *params) +{ + int i; + int w = params->w; + char *keys = smalloc(w+2); + for (i = 0; i < w; i++) { + if (i<9) keys[i] = '1' + i; + else keys[i] = 'a' + i - 9; + } + keys[w] = '\b'; + keys[w+1] = '\0'; + return keys; +} + static game_state *new_game(midend *me, const game_params *params, const char *desc) { @@ -2354,6 +2368,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + game_request_keys, game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/latin.c b/apps/plugins/puzzles/src/latin.c index 50fae3c..716064c 100644 --- a/apps/plugins/puzzles/src/latin.c +++ b/apps/plugins/puzzles/src/latin.c @@ -964,13 +964,30 @@ static int latin_solver_top(struct latin_solver *solver, int maxdiff, got_result: #ifdef STANDALONE_SOLVER - if (solver_show_working) - printf("%*s%s found\n", - solver_recurse_depth*4, "", - diff == diff_impossible ? "no solution (impossible)" : - diff == diff_unfinished ? "no solution (unfinished)" : - diff == diff_ambiguous ? "multiple solutions" : - "one solution"); + if (solver_show_working) { + if (diff != diff_impossible && diff != diff_unfinished && + diff != diff_ambiguous) { + int x, y; + + printf("%*sone solution found:\n", solver_recurse_depth*4, ""); + + for (y = 0; y < solver->o; y++) { + printf("%*s", solver_recurse_depth*4+1, ""); + for (x = 0; x < solver->o; x++) { + int val = solver->grid[y*solver->o+x]; + assert(val); + printf(" %s", solver->names[val-1]); + } + printf("\n"); + } + } else { + printf("%*s%s found\n", + solver_recurse_depth*4, "", + diff == diff_impossible ? "no solution (impossible)" : + diff == diff_unfinished ? "no solution (unfinished)" : + "multiple solutions"); + } + } #endif latin_solver_free_scratch(scratch); diff --git a/apps/plugins/puzzles/src/lightup.c b/apps/plugins/puzzles/src/lightup.c index fd363e0..acee853 100644 --- a/apps/plugins/puzzles/src/lightup.c +++ b/apps/plugins/puzzles/src/lightup.c @@ -2303,6 +2303,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/loopy.c b/apps/plugins/puzzles/src/loopy.c index c14412d..f5f8917 100644 --- a/apps/plugins/puzzles/src/loopy.c +++ b/apps/plugins/puzzles/src/loopy.c @@ -3658,6 +3658,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/magnets.c b/apps/plugins/puzzles/src/magnets.c index ebb5376..c9f97b6 100644 --- a/apps/plugins/puzzles/src/magnets.c +++ b/apps/plugins/puzzles/src/magnets.c @@ -2409,6 +2409,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/map.c b/apps/plugins/puzzles/src/map.c index 3a16335..2037510 100644 --- a/apps/plugins/puzzles/src/map.c +++ b/apps/plugins/puzzles/src/map.c @@ -3236,6 +3236,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/midend.c b/apps/plugins/puzzles/src/midend.c index 4ccb1f9..0c91388 100644 --- a/apps/plugins/puzzles/src/midend.c +++ b/apps/plugins/puzzles/src/midend.c @@ -25,6 +25,11 @@ struct midend_state_entry { int movetype; }; +struct midend_serialise_buf { + char *buf; + int len, size; +}; + struct midend { frontend *frontend; random_state *random; @@ -63,8 +68,8 @@ struct midend { int nstates, statesize, statepos; struct midend_state_entry *states; - char *newgame_undo_buf; - int newgame_undo_len, newgame_undo_size; + struct midend_serialise_buf newgame_undo, newgame_redo; + int newgame_can_store_undo; game_params *params, *curparams; game_drawstate *drawstate; @@ -158,8 +163,11 @@ midend *midend_new(frontend *fe, const game *ourgame, me->random = random_new(randseed, randseedsize); me->nstates = me->statesize = me->statepos = 0; me->states = NULL; - me->newgame_undo_buf = NULL; - me->newgame_undo_size = me->newgame_undo_len = 0; + me->newgame_undo.buf = NULL; + me->newgame_undo.size = me->newgame_undo.len = 0; + me->newgame_redo.buf = NULL; + me->newgame_redo.size = me->newgame_redo.len = 0; + me->newgame_can_store_undo = FALSE; me->params = ourgame->default_params(); me->game_id_change_notify_function = NULL; me->game_id_change_notify_ctx = NULL; @@ -221,6 +229,7 @@ static void midend_purge_states(midend *me) if (me->states[me->nstates].movestr) sfree(me->states[me->nstates].movestr); } + me->newgame_redo.len = 0; } static void midend_free_game(midend *me) @@ -257,7 +266,8 @@ void midend_free(midend *me) if (me->drawing) drawing_free(me->drawing); random_free(me->random); - sfree(me->newgame_undo_buf); + sfree(me->newgame_undo.buf); + sfree(me->newgame_redo.buf); sfree(me->states); sfree(me->desc); sfree(me->privdesc); @@ -386,36 +396,39 @@ void midend_force_redraw(midend *me) static void newgame_serialise_write(void *ctx, const void *buf, int len) { - midend *const me = ctx; + struct midend_serialise_buf *ser = (struct midend_serialise_buf *)ctx; int new_len; - assert(len < INT_MAX - me->newgame_undo_len); - new_len = me->newgame_undo_len + len; - if (new_len > me->newgame_undo_size) { - me->newgame_undo_size = new_len + new_len / 4 + 1024; - me->newgame_undo_buf = sresize(me->newgame_undo_buf, - me->newgame_undo_size, char); + assert(len < INT_MAX - ser->len); + new_len = ser->len + len; + if (new_len > ser->size) { + ser->size = new_len + new_len / 4 + 1024; + ser->buf = sresize(ser->buf, ser->size, char); } - memcpy(me->newgame_undo_buf + me->newgame_undo_len, buf, len); - me->newgame_undo_len = new_len; + memcpy(ser->buf + ser->len, buf, len); + ser->len = new_len; } void midend_new_game(midend *me) { - me->newgame_undo_len = 0; - if (me->nstates != 0) { + me->newgame_undo.len = 0; + if (me->newgame_can_store_undo) { /* * Serialise the whole of the game that we're about to * supersede, so that the 'New Game' action can be undone - * later. But if nstates == 0, that means there _isn't_ a - * current game (not even a starting position), because this - * is the initial call to midend_new_game when the midend is - * first set up; in that situation, we want to avoid writing - * out any serialisation, because it would be useless anyway - * and just confuse us into thinking we had something to undo - * to. + * later. + * + * We omit this in various situations, such as if there + * _isn't_ a current game (not even a starting position) + * because this is the initial call to midend_new_game when + * the midend is first set up, or if the midend state has + * already begun to be overwritten by midend_set_config. In + * those situations, we want to avoid writing out any + * serialisation, because they will be either invalid, or + * worse, valid but wrong. */ - midend_serialise(me, newgame_serialise_write, me); + midend_purge_states(me); + midend_serialise(me, newgame_serialise_write, &me->newgame_undo); } midend_stop_anim(me); @@ -528,30 +541,31 @@ void midend_new_game(midend *me) if (me->game_id_change_notify_function) me->game_id_change_notify_function(me->game_id_change_notify_ctx); + + me->newgame_can_store_undo = TRUE; } int midend_can_undo(midend *me) { - return (me->statepos > 1 || me->newgame_undo_len); + return (me->statepos > 1 || me->newgame_undo.len); } int midend_can_redo(midend *me) { - return (me->statepos < me->nstates); + return (me->statepos < me->nstates || me->newgame_redo.len); } struct newgame_undo_deserialise_read_ctx { - midend *me; + struct midend_serialise_buf *ser; int len, pos; }; static int newgame_undo_deserialise_read(void *ctx, void *buf, int len) { struct newgame_undo_deserialise_read_ctx *const rctx = ctx; - midend *const me = rctx->me; int use = min(len, rctx->len - rctx->pos); - memcpy(buf, me->newgame_undo_buf + rctx->pos, use); + memcpy(buf, rctx->ser->buf + rctx->pos, use); rctx->pos += use; return use; } @@ -624,12 +638,22 @@ static int midend_undo(midend *me) me->statepos--; me->dir = -1; return 1; - } else if (me->newgame_undo_len) { - /* This undo cannot be undone with redo */ + } else if (me->newgame_undo.len) { struct newgame_undo_deserialise_read_ctx rctx; struct newgame_undo_deserialise_check_ctx cctx; - rctx.me = me; - rctx.len = me->newgame_undo_len; /* copy for reentrancy safety */ + struct midend_serialise_buf serbuf; + + /* + * Serialise the current game so that you can later redo past + * this undo. Once we're committed to the undo actually + * happening, we'll copy this data into place. + */ + serbuf.buf = NULL; + serbuf.len = serbuf.size = 0; + midend_serialise(me, newgame_serialise_write, &serbuf); + + rctx.ser = &me->newgame_undo; + rctx.len = me->newgame_undo.len; /* copy for reentrancy safety */ rctx.pos = 0; cctx.refused = FALSE; deserialise_error = midend_deserialise_internal( @@ -642,6 +666,7 @@ static int midend_undo(midend *me) * contain the dummy error message generated by our check * function, which we ignore.) */ + sfree(serbuf.buf); return 0; } else { /* @@ -652,6 +677,22 @@ static int midend_undo(midend *me) * replaced by the wrong file, etc., by user error. */ assert(!deserialise_error); + + /* + * Clear the old newgame_undo serialisation, so that we + * don't try to undo past the beginning of the game we've + * just gone back to and end up at the front of it again. + */ + me->newgame_undo.len = 0; + + /* + * Copy the serialisation of the game we've just left into + * the midend so that we can redo back into it later. + */ + me->newgame_redo.len = 0; + newgame_serialise_write(&me->newgame_redo, serbuf.buf, serbuf.len); + + sfree(serbuf.buf); return 1; } } else @@ -660,6 +701,8 @@ static int midend_undo(midend *me) static int midend_redo(midend *me) { + const char *deserialise_error; + if (me->statepos < me->nstates) { if (me->ui) me->ourgame->changed_state(me->ui, @@ -668,6 +711,63 @@ static int midend_redo(midend *me) me->statepos++; me->dir = +1; return 1; + } else if (me->newgame_redo.len) { + struct newgame_undo_deserialise_read_ctx rctx; + struct newgame_undo_deserialise_check_ctx cctx; + struct midend_serialise_buf serbuf; + + /* + * Serialise the current game so that you can later undo past + * this redo. Once we're committed to the undo actually + * happening, we'll copy this data into place. + */ + serbuf.buf = NULL; + serbuf.len = serbuf.size = 0; + midend_serialise(me, newgame_serialise_write, &serbuf); + + rctx.ser = &me->newgame_redo; + rctx.len = me->newgame_redo.len; /* copy for reentrancy safety */ + rctx.pos = 0; + cctx.refused = FALSE; + deserialise_error = midend_deserialise_internal( + me, newgame_undo_deserialise_read, &rctx, + newgame_undo_deserialise_check, &cctx); + if (cctx.refused) { + /* + * Our post-deserialisation check shows that we can't use + * this saved game after all. (deserialise_error will + * contain the dummy error message generated by our check + * function, which we ignore.) + */ + sfree(serbuf.buf); + return 0; + } else { + /* + * There should never be any _other_ deserialisation + * error, because this serialised data has been held in + * our memory since it was created, and hasn't had any + * opportunity to be corrupted on disk, accidentally + * replaced by the wrong file, etc., by user error. + */ + assert(!deserialise_error); + + /* + * Clear the old newgame_redo serialisation, so that we + * don't try to redo past the end of the game we've just + * come into and end up at the back of it again. + */ + me->newgame_redo.len = 0; + + /* + * Copy the serialisation of the game we've just left into + * the midend so that we can undo back into it later. + */ + me->newgame_undo.len = 0; + newgame_serialise_write(&me->newgame_undo, serbuf.buf, serbuf.len); + + sfree(serbuf.buf); + return 1; + } } else return 0; } @@ -1587,6 +1687,8 @@ static const char *midend_game_id_int(midend *me, const char *id, int defmode) sfree(par); + me->newgame_can_store_undo = FALSE; + return NULL; } @@ -2224,13 +2326,14 @@ static const char *midend_deserialise_internal( me->statepos = data.statepos; /* - * Don't save the "new game undo" state. So "new game" twice or + * Don't save the "new game undo/redo" state. So "new game" twice or * (in some environments) switching away and back, will make a * "new game" irreversible. Maybe in the future we will have a * more sophisticated way to decide when to discard the previous * game state. */ - me->newgame_undo_len = 0; + me->newgame_undo.len = 0; + me->newgame_redo.len = 0; { game_params *tmp; diff --git a/apps/plugins/puzzles/src/mines.c b/apps/plugins/puzzles/src/mines.c index 340bb4b..0a66a25 100644 --- a/apps/plugins/puzzles/src/mines.c +++ b/apps/plugins/puzzles/src/mines.c @@ -3193,6 +3193,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/net.c b/apps/plugins/puzzles/src/net.c index ab2425e..2242633 100644 --- a/apps/plugins/puzzles/src/net.c +++ b/apps/plugins/puzzles/src/net.c @@ -3239,6 +3239,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/netslide.c b/apps/plugins/puzzles/src/netslide.c index d4d9856..af4ef7d 100644 --- a/apps/plugins/puzzles/src/netslide.c +++ b/apps/plugins/puzzles/src/netslide.c @@ -1871,6 +1871,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/nullgame.c b/apps/plugins/puzzles/src/nullgame.c index bc19c1e..13c464c 100644 --- a/apps/plugins/puzzles/src/nullgame.c +++ b/apps/plugins/puzzles/src/nullgame.c @@ -285,6 +285,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/palisade.c b/apps/plugins/puzzles/src/palisade.c index e495bbe..0be8ac5 100644 --- a/apps/plugins/puzzles/src/palisade.c +++ b/apps/plugins/puzzles/src/palisade.c @@ -1390,6 +1390,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/pattern.c b/apps/plugins/puzzles/src/pattern.c index e067f3a..f715df4 100644 --- a/apps/plugins/puzzles/src/pattern.c +++ b/apps/plugins/puzzles/src/pattern.c @@ -2000,6 +2000,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/pearl.c b/apps/plugins/puzzles/src/pearl.c index 4f3be50..07949b5 100644 --- a/apps/plugins/puzzles/src/pearl.c +++ b/apps/plugins/puzzles/src/pearl.c @@ -2621,6 +2621,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/pegs.c b/apps/plugins/puzzles/src/pegs.c index 565ba94..823d5c2 100644 --- a/apps/plugins/puzzles/src/pegs.c +++ b/apps/plugins/puzzles/src/pegs.c @@ -1316,6 +1316,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/puzzles.h b/apps/plugins/puzzles/src/puzzles.h index 47f4b7e..031bdfc 100644 --- a/apps/plugins/puzzles/src/puzzles.h +++ b/apps/plugins/puzzles/src/puzzles.h @@ -613,6 +613,7 @@ struct game { void (*free_ui)(game_ui *ui); char *(*encode_ui)(const game_ui *ui); void (*decode_ui)(game_ui *ui, const char *encoding); + char *(*request_keys)(const game_params *params); void (*changed_state)(game_ui *ui, const game_state *oldstate, const game_state *newstate); char *(*interpret_move)(const game_state *state, game_ui *ui, diff --git a/apps/plugins/puzzles/src/range.c b/apps/plugins/puzzles/src/range.c index 41c6a35..03bdf6d 100644 --- a/apps/plugins/puzzles/src/range.c +++ b/apps/plugins/puzzles/src/range.c @@ -613,15 +613,16 @@ static move *solver_reasoning_recursion(game_state *state, /* FIXME: add enum alias for smallest and largest (or N) */ for (colour = M_BLACK; colour <= M_WHITE; ++colour) { newstate = dup_game(state); - newstate->grid[cell] = colour; + newstate->grid[cell] = colour == M_BLACK ? BLACK : WHITE; recursive_result = do_solve(newstate, nclues, clues, buf, DIFF_RECURSION); - free_game(newstate); if (recursive_result == NULL) { + free_game(newstate); solver_makemove(r, c, M_BLACK + M_WHITE - colour, state, &buf); return buf; } for (i = 0; i < n && newstate->grid[i] != EMPTY; ++i); + free_game(newstate); if (i == n) return buf; } } @@ -1812,6 +1813,7 @@ struct game const thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/rect.c b/apps/plugins/puzzles/src/rect.c index c9923ad..3d84f04 100644 --- a/apps/plugins/puzzles/src/rect.c +++ b/apps/plugins/puzzles/src/rect.c @@ -2977,6 +2977,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/samegame.c b/apps/plugins/puzzles/src/samegame.c index d7d0676..4dfc302 100644 --- a/apps/plugins/puzzles/src/samegame.c +++ b/apps/plugins/puzzles/src/samegame.c @@ -1656,6 +1656,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/signpost.c b/apps/plugins/puzzles/src/signpost.c index edcf63a..04a3152 100644 --- a/apps/plugins/puzzles/src/signpost.c +++ b/apps/plugins/puzzles/src/signpost.c @@ -2247,6 +2247,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/singles.c b/apps/plugins/puzzles/src/singles.c index 5929d82..35c5fce 100644 --- a/apps/plugins/puzzles/src/singles.c +++ b/apps/plugins/puzzles/src/singles.c @@ -1828,6 +1828,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/sixteen.c b/apps/plugins/puzzles/src/sixteen.c index 9fa7032..6bba4c8 100644 --- a/apps/plugins/puzzles/src/sixteen.c +++ b/apps/plugins/puzzles/src/sixteen.c @@ -1189,6 +1189,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/slant.c b/apps/plugins/puzzles/src/slant.c index 3fd6611..5eeb668 100644 --- a/apps/plugins/puzzles/src/slant.c +++ b/apps/plugins/puzzles/src/slant.c @@ -2164,6 +2164,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/solo.c b/apps/plugins/puzzles/src/solo.c index dd04cdf..ac0b807 100644 --- a/apps/plugins/puzzles/src/solo.c +++ b/apps/plugins/puzzles/src/solo.c @@ -510,7 +510,9 @@ static const char *validate_params(const game_params *params, int full) if ((params->c * params->r) > 31) return "Unable to support more than 31 distinct symbols in a puzzle"; if (params->killer && params->c * params->r > 9) - return "Killer puzzle dimensions must be smaller than 10."; + return "Killer puzzle dimensions must be smaller than 10"; + if (params->xtype && params->c * params->r < 4) + return "X-type puzzle dimensions must be larger than 3"; return NULL; } @@ -3103,6 +3105,8 @@ static int check_valid(int cr, struct block_structure *blocks, sfree(used); return FALSE; } + + memset(used, FALSE, cr); for (i = 0; i < cr; i++) if (grid[diag1(i)] > 0 && grid[diag1(i)] <= cr) used[grid[diag1(i)]-1] = TRUE; @@ -3604,6 +3608,20 @@ static struct block_structure *gen_killer_cages(int cr, random_state *rs, return b; } +static char *game_request_keys(const game_params *params) +{ + int i; + int cr = params->c * params->r; + char *keys = smalloc(cr+2); + for (i = 0; i < cr; i++) { + if (i<9) keys[i] = '1' + i; + else keys[i] = 'a' + i - 9; + } + keys[cr] = '\b'; + keys[cr+1] = '\0'; + return keys; +} + static char *new_game_desc(const game_params *params, random_state *rs, char **aux, int interactive) { @@ -5575,6 +5593,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + game_request_keys, game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/tents.c b/apps/plugins/puzzles/src/tents.c index 48d420e..48da7f2 100644 --- a/apps/plugins/puzzles/src/tents.c +++ b/apps/plugins/puzzles/src/tents.c @@ -2626,6 +2626,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/towers.c b/apps/plugins/puzzles/src/towers.c index 9ccc6ae..14b12c6 100644 --- a/apps/plugins/puzzles/src/towers.c +++ b/apps/plugins/puzzles/src/towers.c @@ -864,6 +864,21 @@ static const char *validate_desc(const game_params *params, const char *desc) return NULL; } +static char *game_request_keys(const game_params *params) +{ + int i; + int w = params->w; + char *keys = smalloc(w+2); + keys[0] = '\b'; + for (i = 0; i < w; i++) { + if (i<9) keys[i] = '1' + i; + else keys[i] = 'a' + i - 9; + } + keys[w] = '\b'; + keys[w+1] = '\0'; + return keys; +} + static game_state *new_game(midend *me, const game_params *params, const char *desc) { @@ -1993,6 +2008,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + game_request_keys, game_changed_state, interpret_move, execute_move, @@ -2072,6 +2088,17 @@ int main(int argc, char **argv) break; } + if (really_show_working) { + /* + * Now run the solver again at the last difficulty level we + * tried, but this time with diagnostics enabled. + */ + solver_show_working = really_show_working; + memcpy(s->grid, s->clues->immutable, p->w * p->w); + ret = solver(p->w, s->clues->clues, s->grid, + diff < DIFFCOUNT ? diff : DIFFCOUNT-1); + } + if (diff == DIFFCOUNT) { if (grade) printf("Difficulty rating: ambiguous\n"); @@ -2084,9 +2111,6 @@ int main(int argc, char **argv) else printf("Difficulty rating: %s\n", towers_diffnames[ret]); } else { - solver_show_working = really_show_working; - memcpy(s->grid, s->clues->immutable, p->w * p->w); - ret = solver(p->w, s->clues->clues, s->grid, diff); if (ret != diff) printf("Puzzle is inconsistent\n"); else diff --git a/apps/plugins/puzzles/src/tracks.c b/apps/plugins/puzzles/src/tracks.c index 3899007..5122f89 100644 --- a/apps/plugins/puzzles/src/tracks.c +++ b/apps/plugins/puzzles/src/tracks.c @@ -2646,6 +2646,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/twiddle.c b/apps/plugins/puzzles/src/twiddle.c index cbf6f76..600f445 100644 --- a/apps/plugins/puzzles/src/twiddle.c +++ b/apps/plugins/puzzles/src/twiddle.c @@ -1293,6 +1293,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/undead.c b/apps/plugins/puzzles/src/undead.c index df0735e..87e559a 100644 --- a/apps/plugins/puzzles/src/undead.c +++ b/apps/plugins/puzzles/src/undead.c @@ -1314,6 +1314,11 @@ void num2grid(int num, int width, int height, int *x, int *y) { return; } +static char *game_request_keys(const game_params *params) +{ + return dupstr("GVZ\b"); +} + static game_state *new_game(midend *me, const game_params *params, const char *desc) { @@ -2716,6 +2721,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + game_request_keys, game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/unequal.c b/apps/plugins/puzzles/src/unequal.c index cb477c9..d8204a4 100644 --- a/apps/plugins/puzzles/src/unequal.c +++ b/apps/plugins/puzzles/src/unequal.c @@ -1280,6 +1280,21 @@ fail: return NULL; } +static char *game_request_keys(const game_params *params) +{ + int order = params->order; + char off = (order > 9) ? '0' : '1'; + char *keys = smalloc(order + 2); + int i; + for(i = 0; i < order; i++) { + if (i==10) off = 'a'-10; + keys[i] = i + off; + } + keys[order] = '\b'; + keys[order+1] = '\0'; + return keys; +} + static game_state *new_game(midend *me, const game_params *params, const char *desc) { @@ -2011,6 +2026,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + game_request_keys, game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/unruly.c b/apps/plugins/puzzles/src/unruly.c index 9d2d592..b3057a7 100644 --- a/apps/plugins/puzzles/src/unruly.c +++ b/apps/plugins/puzzles/src/unruly.c @@ -1926,6 +1926,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, diff --git a/apps/plugins/puzzles/src/untangle.c b/apps/plugins/puzzles/src/untangle.c index 09c36fe..0bcd04d 100644 --- a/apps/plugins/puzzles/src/untangle.c +++ b/apps/plugins/puzzles/src/untangle.c @@ -1623,6 +1623,7 @@ const struct game thegame = { free_ui, encode_ui, decode_ui, + NULL, /* game_request_keys */ game_changed_state, interpret_move, execute_move, |