+struct newgame_undo_deserialise_check_ctx {
+ int refused;
+};
+
+static char *newgame_undo_deserialise_check(
+ void *vctx, midend *me, const struct deserialise_data *data)
+{
+ struct newgame_undo_deserialise_check_ctx *ctx =
+ (struct newgame_undo_deserialise_check_ctx *)vctx;
+ char *old, *new;
+
+ /*
+ * Undoing a New Game operation is only permitted if it doesn't
+ * change the game parameters. The point of having the ability at
+ * all is to recover from the momentary finger error of having hit
+ * the 'n' key (perhaps in place of some other nearby key), or hit
+ * the New Game menu item by mistake when aiming for the adjacent
+ * Restart; in both those situations, the game params are the same
+ * before and after the new-game operation.
+ *
+ * In principle, we could generalise this so that _any_ call to
+ * midend_new_game could be undone, but that would need all front
+ * ends to be alert to the possibility that any keystroke passed
+ * to midend_process_key might (if it turns out to have been one
+ * of the synonyms for undo, which the frontend doesn't
+ * necessarily check for) have various knock-on effects like
+ * needing to select a different preset in the game type menu, or
+ * even resizing the window. At least for the moment, it's easier
+ * not to do that, and to simply disallow any newgame-undo that is
+ * disruptive in either of those ways.
+ *
+ * We check both params and cparams, to be as safe as possible.
+ */
+
+ old = me->ourgame->encode_params(me->params, TRUE);
+ new = me->ourgame->encode_params(data->params, TRUE);
+ if (strcmp(old, new)) {
+ /* Set a flag to distinguish this deserialise failure
+ * from one due to faulty decoding */
+ ctx->refused = TRUE;
+ return "Undoing this new-game operation would change params";
+ }
+
+ old = me->ourgame->encode_params(me->curparams, TRUE);
+ new = me->ourgame->encode_params(data->cparams, TRUE);
+ if (strcmp(old, new)) {
+ ctx->refused = TRUE;
+ return "Undoing this new-game operation would change params";
+ }
+
+ /*
+ * Otherwise, fine, go ahead.
+ */
+ return NULL;
+}
+