From: simon Date: Tue, 8 Feb 2011 22:13:18 +0000 (+0000) Subject: Another UI feature for Group: now you can click between two legend X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/commitdiff_plain/a346afcd456e6e1a66d7649447c73ff041980e7f Another UI feature for Group: now you can click between two legend elements to toggle thick lines in the grid. Helps to delineate subgroups and cosets, so it's easier to remember what you can legitimately fill in by associativity. (I should really stop fiddling with this game's UI; it's far too silly.) git-svn-id: svn://svn.tartarus.org/sgt/puzzles@9084 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/unfinished/group.c b/unfinished/group.c index 4c49030..7f7e0a2 100644 --- a/unfinished/group.c +++ b/unfinished/group.c @@ -87,6 +87,22 @@ struct game_state { int *pencil; /* bitmaps using bits 1<<1..1<pencil[i] = 0; } state->sequence = snewn(w, digit); + state->dividers = snewn(w, int); for (i = 0; i < w; i++) { state->sequence[i] = i; + state->dividers[i] = -1; } desc = spec_to_grid(desc, state->grid, a); @@ -868,10 +886,12 @@ static game_state *dup_game(game_state *state) ret->immutable = snewn(a, unsigned char); ret->pencil = snewn(a, int); ret->sequence = snewn(w, digit); + ret->dividers = snewn(w, int); memcpy(ret->grid, state->grid, a*sizeof(digit)); memcpy(ret->immutable, state->immutable, a*sizeof(unsigned char)); memcpy(ret->pencil, state->pencil, a*sizeof(int)); memcpy(ret->sequence, state->sequence, w*sizeof(digit)); + memcpy(ret->dividers, state->dividers, w*sizeof(int)); ret->completed = state->completed; ret->cheated = state->cheated; @@ -992,6 +1012,7 @@ struct game_ui { int drag; /* 0=none 1=row 2=col */ int dragnum; /* element being dragged */ int dragpos; /* its current position */ + int edgepos; }; static game_ui *new_ui(game_state *state) @@ -1045,6 +1066,10 @@ static void game_changed_state(game_ui *ui, game_state *oldstate, #define FLASH_TIME 0.4F +#define DF_DIVIDER_TOP 0x1000 +#define DF_DIVIDER_BOT 0x2000 +#define DF_DIVIDER_LEFT 0x4000 +#define DF_DIVIDER_RIGHT 0x8000 #define DF_HIGHLIGHT 0x0400 #define DF_HIGHLIGHT_PENCIL 0x0200 #define DF_IMMUTABLE 0x0100 @@ -1190,17 +1215,29 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, if (ui->drag) { if (IS_MOUSE_DRAG(button)) { - int tcoord = (ui->drag == 1 ? ty : tx); + int tcoord = ((ui->drag &~ 4) == 1 ? ty : tx); + ui->drag |= 4; /* some movement has happened */ if (tcoord >= 0 && tcoord < w) { ui->dragpos = tcoord; return ""; } } else if (IS_MOUSE_RELEASE(button)) { - ui->drag = 0; /* end drag */ - if (state->sequence[ui->dragpos] == ui->dragnum) - return ""; /* drag was a no-op overall */ - sprintf(buf, "D%d,%d", ui->dragnum, ui->dragpos); - return dupstr(buf); + if (ui->drag & 4) { + ui->drag = 0; /* end drag */ + if (state->sequence[ui->dragpos] == ui->dragnum) + return ""; /* drag was a no-op overall */ + sprintf(buf, "D%d,%d", ui->dragnum, ui->dragpos); + return dupstr(buf); + } else { + ui->drag = 0; /* end 'drag' */ + if (ui->edgepos > 0 && ui->edgepos < w) { + sprintf(buf, "V%d,%d", + state->sequence[ui->edgepos-1], + state->sequence[ui->edgepos]); + return dupstr(buf); + } else + return ""; /* no-op */ + } } } else if (IS_MOUSE_DOWN(button)) { if (tx >= 0 && tx < w && ty >= 0 && ty < w) { @@ -1243,11 +1280,13 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, ui->drag = 2; ui->dragnum = state->sequence[tx]; ui->dragpos = tx; + ui->edgepos = FROMCOORD(x + TILESIZE/2); return ""; } else if (ty >= 0 && ty < w && tx == -1) { ui->drag = 1; ui->dragnum = state->sequence[ty]; ui->dragpos = ty; + ui->edgepos = FROMCOORD(y + TILESIZE/2); return ""; } } @@ -1369,6 +1408,22 @@ static game_state *execute_move(game_state *from, char *move) ret->sequence[i] = from->sequence[j++]; } } + /* + * Eliminate any obsoleted dividers. + */ + for (x = 0; x+1 < w; x++) { + int i = ret->sequence[x], j = ret->sequence[x+1]; + if (ret->dividers[i] != j) + ret->dividers[i] = -1; + } + return ret; + } else if (move[0] == 'V' && + sscanf(move+1, "%d,%d", &i, &j) == 2) { + ret = dup_game(from); + if (ret->dividers[i] == j) + ret->dividers[i] = -1; + else + ret->dividers[i] = j; return ret; } else return NULL; /* couldn't parse move string */ @@ -1490,6 +1545,16 @@ static void draw_tile(drawing *dr, game_drawstate *ds, int x, int y, long tile, draw_rect(dr, cx, cy, cw, ch, (tile & DF_HIGHLIGHT) ? COL_HIGHLIGHT : COL_BACKGROUND); + /* dividers */ + if (tile & DF_DIVIDER_TOP) + draw_rect(dr, cx, cy, cw, 1, COL_GRID); + if (tile & DF_DIVIDER_BOT) + draw_rect(dr, cx, cy+ch-1, cw, 1, COL_GRID); + if (tile & DF_DIVIDER_LEFT) + draw_rect(dr, cx, cy, 1, ch, COL_GRID); + if (tile & DF_DIVIDER_RIGHT) + draw_rect(dr, cx+cw-1, cy, 1, ch, COL_GRID); + /* pencil-mode highlight */ if (tile & DF_HIGHLIGHT_PENCIL) { int coords[6]; @@ -1699,8 +1764,8 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, if (state->immutable[sy*w+sx]) tile |= DF_IMMUTABLE; - if ((ui->drag == 1 && ui->dragnum == sy) || - (ui->drag == 2 && ui->dragnum == sx)) + if ((ui->drag == 5 && ui->dragnum == sy) || + (ui->drag == 6 && ui->dragnum == sx)) tile |= DF_HIGHLIGHT; else if (ui->hshow && ui->hx == sx && ui->hy == sy) tile |= (ui->hpencil ? DF_HIGHLIGHT_PENCIL : DF_HIGHLIGHT); @@ -1710,6 +1775,15 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, flashtime >= FLASH_TIME*2/3)) tile |= DF_HIGHLIGHT; /* completion flash */ + if (y <= 0 || state->dividers[ds->sequence[y-1]] == sy) + tile |= DF_DIVIDER_TOP; + if (y+1 >= w || state->dividers[sy] == ds->sequence[y+1]) + tile |= DF_DIVIDER_BOT; + if (x <= 0 || state->dividers[ds->sequence[x-1]] == sx) + tile |= DF_DIVIDER_LEFT; + if (x+1 >= w || state->dividers[sx] == ds->sequence[x+1]) + tile |= DF_DIVIDER_RIGHT; + error = ds->errtmp[sy*w+sx]; if (ds->tiles[y*w+x] != tile ||