X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/b760b8bdf1ff5b603e3076c8e21cf246d08937f7..3126844d5216733a1a95abb913265c2fa567ff46:/pearl.c diff --git a/pearl.c b/pearl.c index c018d5a..fe6b9c3 100644 --- a/pearl.c +++ b/pearl.c @@ -1335,6 +1335,8 @@ static int new_clues(game_params *params, random_state *rs, break; /* got it */ } + debug(("%d %dx%d loops before finished puzzle.\n", ngen, w, h)); + return ngen; } @@ -1343,14 +1345,12 @@ static char *new_game_desc(game_params *params, random_state *rs, { char *grid, *clues; char *desc; - int ngen, w = params->w, h = params->h, i, j; + int w = params->w, h = params->h, i, j; grid = snewn(w*h, char); clues = snewn(w*h, char); - ngen = new_clues(params, rs, clues, grid); - - debug(("%d %dx%d loops before finished puzzle.\n", ngen, w, h)); + new_clues(params, rs, clues, grid); desc = snewn(w * h + 1, char); for (i = j = 0; i < w*h; i++) { @@ -1836,7 +1836,15 @@ static void update_ui_drag(game_state *state, game_ui *ui, int gx, int gy) if (ox == gx || oy == gy) { int dx = (gx < ox ? -1 : gx > ox ? +1 : 0); int dy = (gy < oy ? -1 : gy > oy ? +1 : 0); + int dir = (dy>0 ? D : dy<0 ? U : dx>0 ? R : L); while (ox != gx || oy != gy) { + /* + * If the drag attempts to cross a 'no line here' mark, + * stop there. We physically don't allow the user to drag + * over those marks. + */ + if (state->marks[oy*w+ox] & dir) + break; ox += dx; oy += dy; ui->dragcoords[ui->ndragcoords++] = oy * w + ox; @@ -1907,7 +1915,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int gx = FROMCOORD(x), gy = FROMCOORD(y), i; char tmpbuf[80]; - if (button == LEFT_BUTTON) { + if (IS_MOUSE_DOWN(button)) { if (!INGRID(state, gx, gy)) return NULL; ui->clickx = x; ui->clicky = y; @@ -1917,7 +1925,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, return ""; } - if (IS_MOUSE_DRAG(button)) { + if (button == LEFT_DRAG) { update_ui_drag(state, ui, gx, gy); return ""; } @@ -1953,11 +1961,25 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, return buf ? buf : ""; } else { - /* Click (or tiny drag). Work out which edge we were closest to. */ - int cx = COORD(gx) + TILE_SIZE/2, cy = COORD(gy) + TILE_SIZE/2; + /* Click (or tiny drag). Work out which edge we were + * closest to. */ + int cx, cy; int gx2, gy2, l1, l2, ismark = (button == RIGHT_RELEASE); char movec = ismark ? 'M' : 'F'; + /* + * We process clicks based on the mouse-down location, + * because that's more natural for a user to carefully + * control than the mouse-up. + */ + x = ui->clickx; + y = ui->clicky; + + gx = FROMCOORD(x); + gy = FROMCOORD(y); + cx = COORD(gx) + TILE_SIZE/2; + cy = COORD(gy) + TILE_SIZE/2; + if (!INGRID(state, gx, gy)) return ""; if (max(abs(x-cx),abs(y-cy)) < TILE_SIZE/4) { @@ -2023,9 +2045,6 @@ static game_state *execute_move(game_state *state, char *move) if (!INGRID(state, x, y)) goto badmove; if (l < 0 || l > 15) goto badmove; - /* TODO trying to set a line over a no-line mark should be - * a failed move? */ - if (c == 'L') ret->lines[y*w + x] |= (char)l; else if (c == 'N') @@ -2038,6 +2057,16 @@ static game_state *execute_move(game_state *state, char *move) else if (c == 'M') ret->marks[y*w + x] ^= (char)l; + /* + * If we ended up trying to lay a line _over_ a mark, + * that's a failed move: interpret_move() should have + * ensured we never received a move string like that in + * the first place. + */ + if ((ret->lines[y*w + x] & (char)l) && + (ret->marks[y*w + x] & (char)l)) + goto badmove; + move += n; } else if (strcmp(move, "H") == 0) { pearl_solve(ret->shared->w, ret->shared->h,