shithub: puzzles

Download patch

ref: 97b03cc67a31c1d0869a21c50b9ca31f78775ff9
parent: 896a73bd7ff8cbde44e97d89cef57346478f0072
author: Ben Harris <bjh21@bjh21.me.uk>
date: Sat Feb 11 17:49:36 EST 2023

Don't allow moves that change the constraints in Unequal

Unequal has a flags word per cell.  Some of those flags are fixed,
like the locations of the ">" signs, but others indicate errors and
are used to allow the player to mark clues as "spent".  Move strings
beginning with "F" allow the user to change the "spent" flags, but
they shouldn't allow the user to change any other flags, especially
those marking the constraints.

Without this fix, the following save file gives a "solver_nminmax:
Assertion `x >= 0 && y >= 0 && x < o && y < o' failed" after it adds a
clue that points off the board:

SAVEFILE:41:Simon Tatham's Portable Puzzle Collection
GAME    :7:Unequal
PARAMS  :3:3e0
CPARAMS :3:3e0
DESC    :17:0,0,0,0,0,0,0,0,0
NSTATES :2:3
STATEPOS:1:3
MOVE    :6:F2,0,4
MOVE    :1:H

--- a/unequal.c
+++ b/unequal.c
@@ -84,6 +84,7 @@
 #define ADJ_TO_SPENT(x) ((x) << 9)
 
 #define F_ERROR_MASK (F_ERROR|F_ERROR_UP|F_ERROR_RIGHT|F_ERROR_DOWN|F_ERROR_LEFT)
+#define F_SPENT_MASK (F_SPENT_UP|F_SPENT_RIGHT|F_SPENT_DOWN|F_SPENT_LEFT)
 
 struct game_state {
     int order;
@@ -1706,7 +1707,8 @@
         check_complete(ret->nums, ret, true);
         return ret;
     } else if (move[0] == 'F' && sscanf(move+1, "%d,%d,%d", &x, &y, &n) == 3 &&
-	       x >= 0 && x < state->order && y >= 0 && y < state->order) {
+	       x >= 0 && x < state->order && y >= 0 && y < state->order &&
+               (n & ~F_SPENT_MASK) == 0) {
 	ret = dup_game(state);
 	GRID(ret, flags, x, y) ^= n;
 	return ret;