X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/b42022848a4c9a8e63fd5823a904507b9bd34b6c..ca58cbd15a357784d0877d64a62b4c227610db50:/map.c diff --git a/map.c b/map.c index 0a41f78..b06e664 100644 --- a/map.c +++ b/map.c @@ -7,7 +7,6 @@ * * - clue marking * - better four-colouring algorithm? - * - ability to drag a set of pencil marks? */ #include @@ -2170,6 +2169,7 @@ static void free_game(game_state *state) sfree(state->map->regiony); sfree(state->map); } + sfree(state->pencil); sfree(state->colouring); sfree(state); } @@ -2240,7 +2240,16 @@ static char *game_text_format(game_state *state) } struct game_ui { - int drag_colour; /* -1 means no drag active */ + /* + * drag_colour: + * + * - -2 means no drag currently active. + * - >=0 means we're dragging a solid colour. + * - -1 means we're dragging a blank space, and drag_pencil + * might or might not add some pencil-mark stipples to that. + */ + int drag_colour; + int drag_pencil; int dragx, dragy; int show_numbers; }; @@ -2318,7 +2327,7 @@ static int region_from_coords(game_state *state, game_drawstate *ds, static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int x, int y, int button) { - char buf[80]; + char *bufp, buf[256]; /* * Enable or disable numeric labels on regions. @@ -2331,10 +2340,15 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, if (button == LEFT_BUTTON || button == RIGHT_BUTTON) { int r = region_from_coords(state, ds, x, y); - if (r >= 0) + if (r >= 0) { ui->drag_colour = state->colouring[r]; - else + ui->drag_pencil = state->pencil[r]; + if (ui->drag_colour >= 0) + ui->drag_pencil = 0; /* should be already, but double-check */ + } else { ui->drag_colour = -1; + ui->drag_pencil = 0; + } ui->dragx = x; ui->dragy = y; return ""; @@ -2351,6 +2365,8 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, ui->drag_colour > -2) { int r = region_from_coords(state, ds, x, y); int c = ui->drag_colour; + int p = ui->drag_pencil; + int oldp; /* * Cancel the drag, whatever happens. @@ -2364,15 +2380,37 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, if (state->map->immutable[r]) return ""; /* can't change this region */ - if (state->colouring[r] == c) + if (state->colouring[r] == c && state->pencil[r] == p) return ""; /* don't _need_ to change this region */ - if (button == RIGHT_RELEASE && state->colouring[r] >= 0) - return ""; /* can't pencil on a coloured region */ + if (button == RIGHT_RELEASE) { + if (state->colouring[r] >= 0) { + /* Can't pencil on a coloured region */ + return ""; + } else if (c >= 0) { + /* Right-dragging from colour to blank toggles one pencil */ + p = state->pencil[r] ^ (1 << c); + c = -1; + } + /* Otherwise, right-dragging from blank to blank is equivalent + * to left-dragging. */ + } - sprintf(buf, "%s%c:%d", (button == RIGHT_RELEASE ? "p" : ""), - (int)(c < 0 ? 'C' : '0' + c), r); - return dupstr(buf); + bufp = buf; + oldp = state->pencil[r]; + if (c != state->colouring[r]) { + bufp += sprintf(bufp, ";%c:%d", (int)(c < 0 ? 'C' : '0' + c), r); + if (c >= 0) + oldp = 0; + } + if (p != oldp) { + int i; + for (i = 0; i < FOUR; i++) + if ((oldp ^ p) & (1 << i)) + bufp += sprintf(bufp, ";p%c:%d", (int)('0' + i), r); + } + + return dupstr(buf+1); /* ignore first semicolon */ } return NULL; @@ -2475,8 +2513,7 @@ static void game_set_size(drawing *dr, game_drawstate *ds, { ds->tilesize = tilesize; - if (ds->bl) - blitter_free(dr, ds->bl); + assert(!ds->bl); /* set_size is never called twice */ ds->bl = blitter_new(dr, TILESIZE+3, TILESIZE+3); } @@ -2577,11 +2614,11 @@ static void draw_error(drawing *dr, game_drawstate *ds, int x, int y) static void draw_square(drawing *dr, game_drawstate *ds, game_params *params, struct map *map, - int x, int y, int v) + int x, int y, unsigned long v) { int w = params->w, h = params->h, wh = w*h; - int tv, bv, xo, yo, errs, pencil, i, j, oldj; - int show_numbers; + int tv, bv, xo, yo, i, j, oldj; + unsigned long errs, pencil, show_numbers; errs = v & ERR_MASK; v &= ~ERR_MASK; @@ -2650,7 +2687,7 @@ static void draw_square(drawing *dr, game_drawstate *ds, draw_circle(dr, COORD(x) + (xo+1)*TILESIZE/5, COORD(y) + (yo+1)*TILESIZE/5, - TILESIZE/8, COL_0 + c, COL_0 + c); + TILESIZE/7, COL_0 + c, COL_0 + c); } /* @@ -2752,7 +2789,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, for (x = 0; x < w; x++) { int tv = state->colouring[state->map->map[TE * wh + y*w+x]]; int bv = state->colouring[state->map->map[BE * wh + y*w+x]]; - int v; + unsigned long v; if (tv < 0) tv = FOUR; @@ -2835,7 +2872,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, */ for (y = 0; y < h; y++) for (x = 0; x < w; x++) { - int v = ds->todraw[y*w+x]; + unsigned long v = ds->todraw[y*w+x]; if (ds->drawn[y*w+x] != v) { draw_square(dr, ds, &state->p, state->map, x, y, v); ds->drawn[y*w+x] = v; @@ -2852,6 +2889,11 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, draw_circle(dr, ui->dragx, ui->dragy, TILESIZE/2, (ui->drag_colour < 0 ? COL_BACKGROUND : COL_0 + ui->drag_colour), COL_GRID); + for (i = 0; i < FOUR; i++) + if (ui->drag_pencil & (1 << i)) + draw_circle(dr, ui->dragx + ((i*4+2)%10-3) * TILESIZE/10, + ui->dragy + (i*2-3) * TILESIZE/10, + TILESIZE/8, COL_0 + i, COL_0 + i); draw_update(dr, ds->dragx, ds->dragy, TILESIZE + 3, TILESIZE + 3); ds->drag_visible = TRUE; } @@ -3085,45 +3127,6 @@ const struct game thegame = { #ifdef STANDALONE_SOLVER -#include - -void frontend_default_colour(frontend *fe, float *output) {} -void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize, - int align, int colour, char *text) {} -void draw_rect(drawing *dr, int x, int y, int w, int h, int colour) {} -void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) {} -void draw_polygon(drawing *dr, int *coords, int npoints, - int fillcolour, int outlinecolour) {} -void draw_circle(drawing *dr, int cx, int cy, int radius, - int fillcolour, int outlinecolour) {} -void clip(drawing *dr, int x, int y, int w, int h) {} -void unclip(drawing *dr) {} -void start_draw(drawing *dr) {} -void draw_update(drawing *dr, int x, int y, int w, int h) {} -void end_draw(drawing *dr) {} -blitter *blitter_new(drawing *dr, int w, int h) {return NULL;} -void blitter_free(drawing *dr, blitter *bl) {} -void blitter_save(drawing *dr, blitter *bl, int x, int y) {} -void blitter_load(drawing *dr, blitter *bl, int x, int y) {} -int print_mono_colour(drawing *dr, int grey) { return 0; } -int print_rgb_colour(drawing *dr, int hatch, float r, float g, float b) -{ return 0; } -void print_line_width(drawing *dr, int width) {} - -void fatal(char *fmt, ...) -{ - va_list ap; - - fprintf(stderr, "fatal error: "); - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - fprintf(stderr, "\n"); - exit(1); -} - int main(int argc, char **argv) { game_params *p;