int rx, ry;
/*
+ * We can't set the size on the same drawstate twice. So if
+ * we've already sized one drawstate, we must throw it away and
+ * create a new one.
+ */
+ if (me->drawstate && me->tilesize > 0) {
+ me->ourgame->free_drawstate(me->drawing, me->drawstate);
+ me->drawstate = me->ourgame->new_drawstate(me->drawing,
+ me->states[0].state);
+ }
+
+ /*
* Find the tile size that best fits within the given space. If
* `expand' is TRUE, we must actually find the _largest_ such
* tile size; otherwise, we bound above at the game's preferred
}
ensure(me);
+
+ /*
+ * It might seem a bit odd that we're using me->params to
+ * create the initial game state, rather than me->curparams
+ * which is better tailored to this specific game and which we
+ * always know.
+ *
+ * It's supposed to be an invariant in the midend that
+ * me->params and me->curparams differ in no aspect that is
+ * important after generation (i.e. after new_desc()). By
+ * deliberately passing the _less_ specific of these two
+ * parameter sets, we provoke play-time misbehaviour in the
+ * case where a game has failed to encode a play-time parameter
+ * in the non-full version of encode_params().
+ */
me->states[me->nstates].state =
me->ourgame->new_game(me, me->params, me->desc);
+
me->states[me->nstates].movestr = NULL;
me->states[me->nstates].movetype = NEWGAME;
me->nstates++;
if (me->statepos < 1)
return "No game set up to solve"; /* _shouldn't_ happen! */
- msg = "Solve operation failed"; /* game _should_ overwrite on error */
+ msg = NULL;
movestr = me->ourgame->solve(me->states[0].state,
me->states[me->statepos-1].state,
me->aux_info, &msg);
- if (!movestr)
+ if (!movestr) {
+ if (!msg)
+ msg = "Solve operation failed"; /* _shouldn't_ happen, but can */
return msg;
+ }
s = me->ourgame->execute_move(me->states[me->statepos-1].state, movestr);
assert(s);