summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-04-17 18:18:40 -0400
committerFranklin Wei <git@fwei.tk>2018-04-17 18:20:12 -0400
commit6dc9d1d7309613fdc0518c03b2cdf3253d4c52fd (patch)
treef6c9abf4a05f640134aa3d248a9498a06f596712 /apps/plugins/puzzles/src
parent7a12e796a62b916dae5de1b2986e8cb11ac5be4c (diff)
downloadrockbox-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')
-rw-r--r--apps/plugins/puzzles/src/blackbox.c1
-rw-r--r--apps/plugins/puzzles/src/bridges.c1
-rw-r--r--apps/plugins/puzzles/src/cube.c1
-rw-r--r--apps/plugins/puzzles/src/dominosa.c1
-rw-r--r--apps/plugins/puzzles/src/fifteen.c1
-rw-r--r--apps/plugins/puzzles/src/filling.c6
-rw-r--r--apps/plugins/puzzles/src/flip.c1
-rw-r--r--apps/plugins/puzzles/src/flood.c1
-rw-r--r--apps/plugins/puzzles/src/galaxies.c1
-rw-r--r--apps/plugins/puzzles/src/guess.c1
-rw-r--r--apps/plugins/puzzles/src/inertia.c1
-rw-r--r--apps/plugins/puzzles/src/keen.c15
-rw-r--r--apps/plugins/puzzles/src/latin.c31
-rw-r--r--apps/plugins/puzzles/src/lightup.c1
-rw-r--r--apps/plugins/puzzles/src/loopy.c1
-rw-r--r--apps/plugins/puzzles/src/magnets.c1
-rw-r--r--apps/plugins/puzzles/src/map.c1
-rw-r--r--apps/plugins/puzzles/src/midend.c173
-rw-r--r--apps/plugins/puzzles/src/mines.c1
-rw-r--r--apps/plugins/puzzles/src/net.c1
-rw-r--r--apps/plugins/puzzles/src/netslide.c1
-rw-r--r--apps/plugins/puzzles/src/nullgame.c1
-rw-r--r--apps/plugins/puzzles/src/palisade.c1
-rw-r--r--apps/plugins/puzzles/src/pattern.c1
-rw-r--r--apps/plugins/puzzles/src/pearl.c1
-rw-r--r--apps/plugins/puzzles/src/pegs.c1
-rw-r--r--apps/plugins/puzzles/src/puzzles.h1
-rw-r--r--apps/plugins/puzzles/src/range.c6
-rw-r--r--apps/plugins/puzzles/src/rect.c1
-rw-r--r--apps/plugins/puzzles/src/samegame.c1
-rw-r--r--apps/plugins/puzzles/src/signpost.c1
-rw-r--r--apps/plugins/puzzles/src/singles.c1
-rw-r--r--apps/plugins/puzzles/src/sixteen.c1
-rw-r--r--apps/plugins/puzzles/src/slant.c1
-rw-r--r--apps/plugins/puzzles/src/solo.c21
-rw-r--r--apps/plugins/puzzles/src/tents.c1
-rw-r--r--apps/plugins/puzzles/src/towers.c30
-rw-r--r--apps/plugins/puzzles/src/tracks.c1
-rw-r--r--apps/plugins/puzzles/src/twiddle.c1
-rw-r--r--apps/plugins/puzzles/src/undead.c6
-rw-r--r--apps/plugins/puzzles/src/unequal.c16
-rw-r--r--apps/plugins/puzzles/src/unruly.c1
-rw-r--r--apps/plugins/puzzles/src/untangle.c1
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,