From 4ec2c580453b0629b9935cb1e90017de6d110608 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 26 Dec 2022 11:25:00 +0000 Subject: [PATCH] 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. --- keen.c | 14 ++++++++++++++ solo.c | 20 ++++++++++++++++++++ towers.c | 14 ++++++++++++++ undead.c | 12 +++++++++++- unequal.c | 19 +++++++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/keen.c b/keen.c index ddb8b64..ec6e512 100644 --- a/keen.c +++ b/keen.c @@ -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]) 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", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); diff --git a/solo.c b/solo.c index f6c7172..addcf80 100644 --- a/solo.c +++ b/solo.c @@ -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]) 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", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); diff --git a/towers.c b/towers.c index 57d6614..e0dad48 100644 --- a/towers.c +++ b/towers.c @@ -1483,6 +1483,20 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (state->clues->immutable[ui->hy*w+ui->hx]) 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", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); diff --git a/undead.c b/undead.c index 46ecce3..70a5f4c 100644 --- a/undead.c +++ b/undead.c @@ -1769,22 +1769,30 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (xi >= 0 && !state->common->fixed[xi]) { if (button == 'g' || button == 'G' || button == '1') { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 1) + return ui->hcursor ? NULL : UI_UPDATE; sprintf(buf,"G%d",xi); return dupstr(buf); } if (button == 'v' || button == 'V' || button == '2') { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 2) + return ui->hcursor ? NULL : UI_UPDATE; sprintf(buf,"V%d",xi); return dupstr(buf); } if (button == 'z' || button == 'Z' || button == '3') { if (!ui->hcursor) ui->hshow = false; + if (state->guess[xi] == 4) + return ui->hcursor ? NULL : UI_UPDATE; sprintf(buf,"Z%d",xi); return dupstr(buf); } if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 || button == '0' || button == '\b' ) { 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); 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 || button == '0' || button == '\b') { - sprintf(buf,"E%d",xi); if (!ui->hcursor) { ui->hpencil = false; ui->hshow = false; } + if (state->pencils[xi] == 0) + return ui->hcursor ? NULL : UI_UPDATE; + sprintf(buf,"E%d",xi); return dupstr(buf); } } diff --git a/unequal.c b/unequal.c index 5e9994f..c1d3a30 100644 --- a/unequal.c +++ b/unequal.c @@ -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) 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", (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);