When filling in or blanking a square, don't generate null moves

This applies to various square-filling games: Keen, Solo, Towers,
Undead, and Unequal.  In all cases, selecting a square and pressing the
number that was already in it, or selecting an empty square and pressing
Backspace, would add a move to the undo chain that did nothing.  This
also meant that the convention where Backspace from the top level of an
application in KaiOS leaves the application didn't work.

Now the various interpret_move() functions check the current state of
the grid, and return NULL or UI_UPDATE where a move wouldn't change the
board.  UI_UPDATE is returned in the case where the cursor was put in
place using the mouse, because in those cases I think the cursor should
still be hidden again.  NULL is returned when the cursor was put in
place by keyboard, because then there's really nothing to do.
This commit is contained in:
Ben Harris
2022-12-26 11:25:00 +00:00
parent d332973438
commit 4ec2c58045
5 changed files with 78 additions and 1 deletions

14
keen.c
View File

@ -1784,6 +1784,20 @@ static char *interpret_move(const game_state *state, game_ui *ui,
if (ui->hpencil && state->grid[ui->hy*w+ui->hx]) if (ui->hpencil && state->grid[ui->hy*w+ui->hx])
return NULL; return NULL;
/*
* If you ask to fill a square with what it already contains,
* or blank it when it's already empty, that has no effect...
*/
if ((!ui->hpencil || n == 0) && state->grid[ui->hy*w+ui->hx] == n &&
state->pencil[ui->hy*w+ui->hx] == 0) {
/* ... expect to remove the cursor in mouse mode. */
if (!ui->hcursor) {
ui->hshow = false;
return UI_UPDATE;
}
return NULL;
}
sprintf(buf, "%c%d,%d,%d", sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);

20
solo.c
View File

@ -4704,6 +4704,26 @@ static char *interpret_move(const game_state *state, game_ui *ui,
if (ui->hpencil && state->grid[ui->hy*cr+ui->hx]) if (ui->hpencil && state->grid[ui->hy*cr+ui->hx])
return NULL; return NULL;
/*
* If you ask to fill a square with what it already contains,
* or blank it when it's already empty, that has no effect...
*/
if ((!ui->hpencil || n == 0) && state->grid[ui->hy*cr+ui->hx] == n) {
bool anypencil = false;
int i;
for (i = 0; i < cr; i++)
anypencil = anypencil ||
state->pencil[(ui->hy*cr+ui->hx) * cr + i];
if (!anypencil) {
/* ... expect to remove the cursor in mouse mode. */
if (!ui->hcursor) {
ui->hshow = false;
return UI_UPDATE;
}
return NULL;
}
}
sprintf(buf, "%c%d,%d,%d", sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);

View File

@ -1483,6 +1483,20 @@ static char *interpret_move(const game_state *state, game_ui *ui,
if (state->clues->immutable[ui->hy*w+ui->hx]) if (state->clues->immutable[ui->hy*w+ui->hx])
return NULL; return NULL;
/*
* If you ask to fill a square with what it already contains,
* or blank it when it's already empty, that has no effect...
*/
if ((!ui->hpencil || n == 0) && state->grid[ui->hy*w+ui->hx] == n &&
state->pencil[ui->hy*w+ui->hx] == 0) {
/* ... expect to remove the cursor in mouse mode. */
if (!ui->hcursor) {
ui->hshow = false;
return UI_UPDATE;
}
return NULL;
}
sprintf(buf, "%c%d,%d,%d", sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);

View File

@ -1769,22 +1769,30 @@ static char *interpret_move(const game_state *state, game_ui *ui,
if (xi >= 0 && !state->common->fixed[xi]) { if (xi >= 0 && !state->common->fixed[xi]) {
if (button == 'g' || button == 'G' || button == '1') { if (button == 'g' || button == 'G' || button == '1') {
if (!ui->hcursor) ui->hshow = false; if (!ui->hcursor) ui->hshow = false;
if (state->guess[xi] == 1)
return ui->hcursor ? NULL : UI_UPDATE;
sprintf(buf,"G%d",xi); sprintf(buf,"G%d",xi);
return dupstr(buf); return dupstr(buf);
} }
if (button == 'v' || button == 'V' || button == '2') { if (button == 'v' || button == 'V' || button == '2') {
if (!ui->hcursor) ui->hshow = false; if (!ui->hcursor) ui->hshow = false;
if (state->guess[xi] == 2)
return ui->hcursor ? NULL : UI_UPDATE;
sprintf(buf,"V%d",xi); sprintf(buf,"V%d",xi);
return dupstr(buf); return dupstr(buf);
} }
if (button == 'z' || button == 'Z' || button == '3') { if (button == 'z' || button == 'Z' || button == '3') {
if (!ui->hcursor) ui->hshow = false; if (!ui->hcursor) ui->hshow = false;
if (state->guess[xi] == 4)
return ui->hcursor ? NULL : UI_UPDATE;
sprintf(buf,"Z%d",xi); sprintf(buf,"Z%d",xi);
return dupstr(buf); return dupstr(buf);
} }
if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 || if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
button == '0' || button == '\b' ) { button == '0' || button == '\b' ) {
if (!ui->hcursor) ui->hshow = false; if (!ui->hcursor) ui->hshow = false;
if (state->guess[xi] == 7 && state->pencils[xi] == 0)
return ui->hcursor ? NULL : UI_UPDATE;
sprintf(buf,"E%d",xi); sprintf(buf,"E%d",xi);
return dupstr(buf); return dupstr(buf);
} }
@ -1841,11 +1849,13 @@ static char *interpret_move(const game_state *state, game_ui *ui,
} }
if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 || if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
button == '0' || button == '\b') { button == '0' || button == '\b') {
sprintf(buf,"E%d",xi);
if (!ui->hcursor) { if (!ui->hcursor) {
ui->hpencil = false; ui->hpencil = false;
ui->hshow = false; ui->hshow = false;
} }
if (state->pencils[xi] == 0)
return ui->hcursor ? NULL : UI_UPDATE;
sprintf(buf,"E%d",xi);
return dupstr(buf); return dupstr(buf);
} }
} }

View File

@ -1612,6 +1612,25 @@ static char *interpret_move(const game_state *state, game_ui *ui,
if (ui->hpencil && GRID(state, nums, ui->hx, ui->hy) > 0) if (ui->hpencil && GRID(state, nums, ui->hx, ui->hy) > 0)
return NULL; /* can't change hints on filled square (!) */ return NULL; /* can't change hints on filled square (!) */
/*
* If you ask to fill a square with what it already contains,
* or blank it when it's already empty, that has no effect...
*/
if ((!ui->hpencil || n == 0) &&
GRID(state, nums, ui->hx, ui->hy) == n) {
bool anypencil = false;
int i;
for (i = 0; i < state->order; i++)
anypencil = anypencil || HINT(state, ui->hx, ui->hy, i);
if (!anypencil) {
/* ... expect to remove the cursor in mouse mode. */
if (!ui->hcursor) {
ui->hshow = false;
return UI_UPDATE;
}
return NULL;
}
}
sprintf(buf, "%c%d,%d,%d", sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);