mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Account for disconnected paths in Loopy and Pearl error highlights.
In commits 24848706e and adc54741f, I revamped the highlighting of erroneous connected components of those two puzzles' solution graphs in cases where a non-solution loop existed, so that the largest component was considered correct and the smaller ones lit up in red. I intended this to work in the cases where you have most of a correct solution as one component and a small spurious loop as another (in which case the latter lights up red), or conversely where your mostly correct component was joined into a loop leaving a few edges out (in which case the left-out edges again light up red). However, a user points out that I overlooked the case where your mostly correct solution is not all one component! If you've got lots of separate pieces of path, and one tiny loop that's definitely wrong, it's silly to light up all but the longest piece of path as if they're erroneous. Fixed by treating all the non-loop components as one unit for these purposes. So if there is at least one loop and it isn't the only thing on the board, then we _either_ light up all loops (if they're all smaller than the set of non-loop paths put together), _or_ light up everything but the largest loop (if that loop is the biggest thing on the board).
This commit is contained in:
44
loopy.c
44
loopy.c
@ -1495,7 +1495,7 @@ static int check_completion(game_state *state)
|
|||||||
grid *g = state->game_grid;
|
grid *g = state->game_grid;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
int *dsf, *component_state;
|
int *dsf, *component_state;
|
||||||
int nsilly, nloop, npath, largest_comp, largest_size;
|
int nsilly, nloop, npath, largest_comp, largest_size, total_pathsize;
|
||||||
enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY };
|
enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY };
|
||||||
|
|
||||||
memset(state->line_errors, 0, g->num_edges);
|
memset(state->line_errors, 0, g->num_edges);
|
||||||
@ -1564,15 +1564,19 @@ static int check_completion(game_state *state)
|
|||||||
* hence they all consist of either a simple loop, or a simple
|
* hence they all consist of either a simple loop, or a simple
|
||||||
* path with two endpoints.
|
* path with two endpoints.
|
||||||
*
|
*
|
||||||
* - If the sensible components are all paths, or if there's
|
* - For these purposes, group together all the paths and imagine
|
||||||
* exactly one of them and it is a loop, then highlight no
|
* them to be a single component (because in most normal
|
||||||
* further edge errors. (The former case is normal during play,
|
* situations the player will gradually build up the solution
|
||||||
* and the latter is a potentially solved puzzle.)
|
* _not_ all in one connected segment, but as lots of separate
|
||||||
|
* little path pieces that gradually connect to each other).
|
||||||
*
|
*
|
||||||
* - Otherwise - if there is more than one sensible component
|
* - After doing that, if there is exactly one (sensible)
|
||||||
* _and_ at least one of them is a loop - find the largest of
|
* component - be it a collection of paths or a loop - then
|
||||||
* the sensible components, leave that one unhighlighted, and
|
* highlight no further edge errors. (The former case is normal
|
||||||
* light the rest up in red.
|
* during play, and the latter is a potentially solved puzzle.)
|
||||||
|
*
|
||||||
|
* - Otherwise, find the largest of the sensible components,
|
||||||
|
* leave that one unhighlighted, and light the rest up in red.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dsf = snew_dsf(g->num_dots);
|
dsf = snew_dsf(g->num_dots);
|
||||||
@ -1640,18 +1644,18 @@ static int check_completion(game_state *state)
|
|||||||
* vertices in the grid data structure, which is fairly arbitrary
|
* vertices in the grid data structure, which is fairly arbitrary
|
||||||
* but at least stays stable throughout the game.) */
|
* but at least stays stable throughout the game.) */
|
||||||
nsilly = nloop = npath = 0;
|
nsilly = nloop = npath = 0;
|
||||||
|
total_pathsize = 0;
|
||||||
largest_comp = largest_size = -1;
|
largest_comp = largest_size = -1;
|
||||||
for (i = 0; i < g->num_dots; i++) {
|
for (i = 0; i < g->num_dots; i++) {
|
||||||
if (component_state[i] == COMP_SILLY) {
|
if (component_state[i] == COMP_SILLY) {
|
||||||
nsilly++;
|
nsilly++;
|
||||||
} else if (component_state[i] == COMP_PATH ||
|
} else if (component_state[i] == COMP_PATH) {
|
||||||
component_state[i] == COMP_LOOP) {
|
total_pathsize += dsf_size(dsf, i);
|
||||||
|
npath = 1;
|
||||||
|
} else if (component_state[i] == COMP_LOOP) {
|
||||||
int this_size;
|
int this_size;
|
||||||
|
|
||||||
if (component_state[i] == COMP_PATH)
|
nloop++;
|
||||||
npath++;
|
|
||||||
else if (component_state[i] == COMP_LOOP)
|
|
||||||
nloop++;
|
|
||||||
|
|
||||||
if ((this_size = dsf_size(dsf, i)) > largest_size) {
|
if ((this_size = dsf_size(dsf, i)) > largest_size) {
|
||||||
largest_comp = i;
|
largest_comp = i;
|
||||||
@ -1659,6 +1663,10 @@ static int check_completion(game_state *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (largest_size < total_pathsize) {
|
||||||
|
largest_comp = -1; /* means the paths */
|
||||||
|
largest_size = total_pathsize;
|
||||||
|
}
|
||||||
|
|
||||||
if (nloop > 0 && nloop + npath > 1) {
|
if (nloop > 0 && nloop + npath > 1) {
|
||||||
/*
|
/*
|
||||||
@ -1671,8 +1679,10 @@ static int check_completion(game_state *state)
|
|||||||
grid_edge *e = g->edges + i;
|
grid_edge *e = g->edges + i;
|
||||||
int d1 = e->dot1 - g->dots; /* either endpoint is good enough */
|
int d1 = e->dot1 - g->dots; /* either endpoint is good enough */
|
||||||
int comp = dsf_canonify(dsf, d1);
|
int comp = dsf_canonify(dsf, d1);
|
||||||
if (component_state[comp] != COMP_SILLY &&
|
if ((component_state[comp] == COMP_PATH &&
|
||||||
comp != largest_comp)
|
-1 != largest_comp) ||
|
||||||
|
(component_state[comp] == COMP_LOOP &&
|
||||||
|
comp != largest_comp))
|
||||||
state->line_errors[i] = TRUE;
|
state->line_errors[i] = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
pearl.c
26
pearl.c
@ -1518,7 +1518,7 @@ static void check_completion(game_state *state, int mark)
|
|||||||
int w = state->shared->w, h = state->shared->h, x, y, i, d;
|
int w = state->shared->w, h = state->shared->h, x, y, i, d;
|
||||||
int had_error = FALSE;
|
int had_error = FALSE;
|
||||||
int *dsf, *component_state;
|
int *dsf, *component_state;
|
||||||
int nsilly, nloop, npath, largest_comp, largest_size;
|
int nsilly, nloop, npath, largest_comp, largest_size, total_pathsize;
|
||||||
enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY };
|
enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY };
|
||||||
|
|
||||||
if (mark) {
|
if (mark) {
|
||||||
@ -1578,18 +1578,18 @@ static void check_completion(game_state *state, int mark)
|
|||||||
|
|
||||||
/* Count the components, and find the largest sensible one. */
|
/* Count the components, and find the largest sensible one. */
|
||||||
nsilly = nloop = npath = 0;
|
nsilly = nloop = npath = 0;
|
||||||
|
total_pathsize = 0;
|
||||||
largest_comp = largest_size = -1;
|
largest_comp = largest_size = -1;
|
||||||
for (i = 0; i < w*h; i++) {
|
for (i = 0; i < w*h; i++) {
|
||||||
if (component_state[i] == COMP_SILLY) {
|
if (component_state[i] == COMP_SILLY) {
|
||||||
nsilly++;
|
nsilly++;
|
||||||
} else if (component_state[i] == COMP_PATH ||
|
} else if (component_state[i] == COMP_PATH) {
|
||||||
component_state[i] == COMP_LOOP) {
|
total_pathsize += dsf_size(dsf, i);
|
||||||
|
npath = 1;
|
||||||
|
} else if (component_state[i] == COMP_LOOP) {
|
||||||
int this_size;
|
int this_size;
|
||||||
|
|
||||||
if (component_state[i] == COMP_PATH)
|
nloop++;
|
||||||
npath++;
|
|
||||||
else if (component_state[i] == COMP_LOOP)
|
|
||||||
nloop++;
|
|
||||||
|
|
||||||
if ((this_size = dsf_size(dsf, i)) > largest_size) {
|
if ((this_size = dsf_size(dsf, i)) > largest_size) {
|
||||||
largest_comp = i;
|
largest_comp = i;
|
||||||
@ -1597,6 +1597,10 @@ static void check_completion(game_state *state, int mark)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (largest_size < total_pathsize) {
|
||||||
|
largest_comp = -1; /* means the paths */
|
||||||
|
largest_size = total_pathsize;
|
||||||
|
}
|
||||||
|
|
||||||
if (nloop > 0 && nloop + npath > 1) {
|
if (nloop > 0 && nloop + npath > 1) {
|
||||||
/*
|
/*
|
||||||
@ -1606,8 +1610,12 @@ static void check_completion(game_state *state, int mark)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < w*h; i++) {
|
for (i = 0; i < w*h; i++) {
|
||||||
int comp = dsf_canonify(dsf, i);
|
int comp = dsf_canonify(dsf, i);
|
||||||
if ((component_state[comp] == COMP_LOOP ||
|
if (component_state[comp] == COMP_PATH)
|
||||||
component_state[comp] == COMP_PATH) && comp != largest_comp)
|
comp = -1; /* part of the 'all paths' quasi-component */
|
||||||
|
if ((component_state[comp] == COMP_PATH &&
|
||||||
|
-1 != largest_comp) ||
|
||||||
|
(component_state[comp] == COMP_LOOP &&
|
||||||
|
comp != largest_comp))
|
||||||
ERROR(i%w, i/w, state->lines[i]);
|
ERROR(i%w, i/w, state->lines[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user