X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/f536db212cbdc22c6880051e32efc2d53163c0ea..HEAD:/unfinished/group.c diff --git a/unfinished/group.c b/unfinished/group.c index 037547e..1c2c02e 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 @@ -1176,8 +1201,20 @@ static int check_errors(game_state *state, long *errors) return errs; } -static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, - int x, int y, int button) +static int find_in_sequence(digit *seq, int len, digit n) +{ + int i; + + for (i = 0; i < len; i++) + if (seq[i] == n) + return i; + + assert(!"Should never get here"); + return -1; +} + +static char *interpret_move(game_state *state, game_ui *ui, + const game_drawstate *ds, int x, int y, int button) { int w = state->par.w; int tx, ty; @@ -1190,17 +1227,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,17 +1292,23 @@ 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 ""; } } if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->hx, &ui->hy, w, w, 0); + int cx = find_in_sequence(state->sequence, w, ui->hx); + int cy = find_in_sequence(state->sequence, w, ui->hy); + move_cursor(button, &cx, &cy, w, w, 0); + ui->hx = state->sequence[cx]; + ui->hy = state->sequence[cy]; ui->hshow = ui->hcursor = 1; return ""; } @@ -1369,6 +1424,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 +1561,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 +1780,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,7 +1791,16 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, flashtime >= FLASH_TIME*2/3)) tile |= DF_HIGHLIGHT; /* completion flash */ - error = ds->errtmp[y*w+x]; + 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 || ds->pencil[y*w+x] != pencil || @@ -1739,6 +1829,11 @@ static float game_flash_length(game_state *oldstate, game_state *newstate, return 0.0F; } +static int game_status(game_state *state) +{ + return state->completed ? +1 : 0; +} + static int game_timing_state(game_state *state, game_ui *ui) { if (state->completed) @@ -1857,6 +1952,7 @@ const struct game thegame = { game_redraw, game_anim_length, game_flash_length, + game_status, TRUE, FALSE, game_print_size, game_print, FALSE, /* wants_statusbar */ FALSE, game_timing_state,