Tolerate incorrect solutions in Inertia

The "solve" operation in Inertia generates a proposed solution as a
move string.  But if such a move string is loaded from a save file it
might not actually describe a solution.  If that happens then it's
possible to reach the end of the "solution" without winning, and doing
so should probably cause a recalculation of the solution rather than
an assertion failure ("execute_move: Assertion `ret->solnpos <
ret->soln->len' failed.").

I am a little concerned by the way that normal solve operations end up
encoded in the save file, but the re-solvings caused by going off
course don't, but I haven't got a good answer to that.

Here's a save file that demonstrates the assertion failure:

SAVEFILE:41:Simon Tatham's Portable Puzzle Collection
GAME    :7:Inertia
PARAMS  :3:8x8
CPARAMS :3:8x8
DESC    :64:sbgwsmswwgggwggmmbwgwbssbwbsbwbbwsSmwbbsbbmggbmssgmgwbmmwmbmmwsw
NSTATES :2:3
STATEPOS:1:1
MOVE 000:2:S0
MOVE 000:2:00
This commit is contained in:
Ben Harris
2023-02-03 20:52:05 +00:00
parent 15f4fa851a
commit 843d4ca17d

View File

@ -1741,11 +1741,10 @@ static game_state *execute_move(const game_state *state, const char *move)
if (ret->soln) { if (ret->soln) {
if (ret->dead || ret->gems == 0) if (ret->dead || ret->gems == 0)
discard_solution(ret); discard_solution(ret);
else if (ret->soln->list[ret->solnpos] == dir) { else if (ret->soln->list[ret->solnpos] == dir &&
ret->solnpos+1 < ret->soln->len)
++ret->solnpos; ++ret->solnpos;
assert(ret->solnpos < ret->soln->len); /* or gems == 0 */ else {
assert(!ret->dead); /* or not a solution */
} else {
const char *error = NULL; const char *error = NULL;
char *soln = solve_game(NULL, ret, NULL, &error); char *soln = solve_game(NULL, ret, NULL, &error);
if (!error) { if (!error) {