mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Loopy: optional 'autofollow' UI feature.
This is mostly intended to make play more convenient for grid types like the new Great-Great-Dodecagonal, and other grids with very high-degree faces, in which it's annoying to have to spend half a dozen mouse clicks on filling in a path of edges round the outside of one of those faces which clearly have to all be set (or clear) if any one of them is. For now, the new feature is enabled by yet another of my hacky environment variables, called LOOPY_AUTOFOLLOW. You can set it to "off", "fixed" or "adaptive", where "off" is currently the default (hence, no user-visible change in the default behaviour from this change). If set to 'fixed', then toggling the state of any edge will automatically toggle any further edges which are in the same state and share a degree-2 vertex of the underlying grid design with the original one. In 'adaptive' mode, the game goes even further, and will consider outgoing edges in LINE_NO state not to count for purposes of deciding if a vertex has degree 2.
This commit is contained in:
62
loopy.c
62
loopy.c
@ -2947,7 +2947,8 @@ static char *interpret_move(const game_state *state, game_ui *ui,
|
||||
grid *g = state->game_grid;
|
||||
grid_edge *e;
|
||||
int i;
|
||||
char *ret, buf[80];
|
||||
char *movebuf;
|
||||
int movelen, movesize;
|
||||
char button_char = ' ';
|
||||
enum line_state old_state;
|
||||
|
||||
@ -3009,11 +3010,64 @@ static char *interpret_move(const game_state *state, game_ui *ui,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
movelen = 0;
|
||||
movesize = 80;
|
||||
movebuf = snewn(movesize, char);
|
||||
movelen = sprintf(movebuf, "%d%c", i, (int)button_char);
|
||||
{
|
||||
static enum { OFF, FIXED, ADAPTIVE, DUNNO } autofollow = DUNNO;
|
||||
if (autofollow == DUNNO) {
|
||||
const char *env = getenv("LOOPY_AUTOFOLLOW");
|
||||
if (env && !strcmp(env, "off"))
|
||||
autofollow = OFF;
|
||||
else if (env && !strcmp(env, "fixed"))
|
||||
autofollow = FIXED;
|
||||
else if (env && !strcmp(env, "adaptive"))
|
||||
autofollow = ADAPTIVE;
|
||||
else
|
||||
autofollow = OFF;
|
||||
}
|
||||
|
||||
sprintf(buf, "%d%c", i, (int)button_char);
|
||||
ret = dupstr(buf);
|
||||
if (autofollow != OFF) {
|
||||
int dotid;
|
||||
for (dotid = 0; dotid < 2; dotid++) {
|
||||
grid_dot *dot = (dotid == 0 ? e->dot1 : e->dot2);
|
||||
grid_edge *e_this = e;
|
||||
|
||||
return ret;
|
||||
while (1) {
|
||||
int j, n_found;
|
||||
grid_edge *e_next = NULL;
|
||||
|
||||
for (j = n_found = 0; j < dot->order; j++) {
|
||||
grid_edge *e_candidate = dot->edges[j];
|
||||
int i_candidate = e_candidate - g->edges;
|
||||
if (e_candidate != e_this &&
|
||||
(autofollow == FIXED ||
|
||||
state->lines[i] == LINE_NO ||
|
||||
state->lines[i_candidate] != LINE_NO)) {
|
||||
e_next = e_candidate;
|
||||
n_found++;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_found != 1 ||
|
||||
state->lines[e_next - g->edges] != state->lines[i])
|
||||
break;
|
||||
|
||||
dot = (e_next->dot1 != dot ? e_next->dot1 : e_next->dot2);
|
||||
if (movelen > movesize - 40) {
|
||||
movesize = movesize * 5 / 4 + 128;
|
||||
movebuf = sresize(movebuf, movesize, char);
|
||||
}
|
||||
e_this = e_next;
|
||||
movelen += sprintf(movebuf+movelen, "%d%c",
|
||||
(int)(e_this - g->edges), button_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sresize(movebuf, movelen+1, char);
|
||||
}
|
||||
|
||||
static game_state *execute_move(const game_state *state, const char *move)
|
||||
|
Reference in New Issue
Block a user