mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 23:51:29 -07:00
Tracks: Highlight more counting errors if track looks good
Normally, Tracks puts error marks on row and column clues only when one of the existing track or no-track marks will have to be removed to satisfy the clue. This could lead to a situation where the player had built a track from A to B and got neither a win nor a highlighted error because the only error was in a row or column having too few track segments. This commit re-arranges the completion checking so that if there's a complete track from A to B and no spurious track then the game will highlight any clue that isn't matched by the actually laid track. This should mean that any solution with a track from A to B will either be a win or have a highlighted error. This should fix Android issue #266.
This commit is contained in:
118
tracks.c
118
tracks.c
@ -1823,7 +1823,7 @@ static int tracks_neighbour(int vertex, void *vctx)
|
||||
static bool check_completion(game_state *state, bool mark)
|
||||
{
|
||||
int w = state->p.w, h = state->p.h, x, y, i, target;
|
||||
bool ret = true;
|
||||
bool ret = true, pathret;
|
||||
int ntrack, nnotrack, ntrackcomplete;
|
||||
int *dsf, pathclass;
|
||||
struct findloopstate *fls;
|
||||
@ -1844,58 +1844,6 @@ static bool check_completion(game_state *state, bool mark)
|
||||
}
|
||||
}
|
||||
|
||||
/* A cell is 'complete', for the purposes of marking the game as
|
||||
* finished, if it has two edges marked as TRACK. But it only has
|
||||
* to have one edge marked as TRACK, or be filled in as trackful
|
||||
* without any specific edges known, to count towards checking
|
||||
* row/column clue errors. */
|
||||
for (x = 0; x < w; x++) {
|
||||
target = state->numbers->numbers[x];
|
||||
ntrack = nnotrack = ntrackcomplete = 0;
|
||||
for (y = 0; y < h; y++) {
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) > 0 ||
|
||||
state->sflags[y*w+x] & S_TRACK)
|
||||
ntrack++;
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) == 2)
|
||||
ntrackcomplete++;
|
||||
if (state->sflags[y*w+x] & S_NOTRACK)
|
||||
nnotrack++;
|
||||
}
|
||||
if (mark) {
|
||||
if (ntrack > target || nnotrack > (h-target)) {
|
||||
debug(("col %d error: target %d, track %d, notrack %d",
|
||||
x, target, ntrack, nnotrack));
|
||||
state->num_errors[x] = 1;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (ntrackcomplete != target)
|
||||
ret = false;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
target = state->numbers->numbers[w+y];
|
||||
ntrack = nnotrack = ntrackcomplete = 0;
|
||||
for (x = 0; x < w; x++) {
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) > 0 ||
|
||||
state->sflags[y*w+x] & S_TRACK)
|
||||
ntrack++;
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) == 2)
|
||||
ntrackcomplete++;
|
||||
if (state->sflags[y*w+x] & S_NOTRACK)
|
||||
nnotrack++;
|
||||
}
|
||||
if (mark) {
|
||||
if (ntrack > target || nnotrack > (w-target)) {
|
||||
debug(("row %d error: target %d, track %d, notrack %d",
|
||||
y, target, ntrack, nnotrack));
|
||||
state->num_errors[w+y] = 1;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (ntrackcomplete != target)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
dsf = snewn(w*h, int);
|
||||
dsf_init(dsf, w*h);
|
||||
|
||||
@ -1949,6 +1897,70 @@ static bool check_completion(game_state *state, bool mark)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A cell is 'complete', for the purposes of marking the game as
|
||||
* finished, if it has two edges marked as TRACK. But it only has
|
||||
* to have one edge marked as TRACK, or be filled in as trackful
|
||||
* without any specific edges known, to count towards checking
|
||||
* row/column clue errors.
|
||||
*
|
||||
* This changes if we haven't found any other errors by this
|
||||
* point, so the player has constructed a route from A to B. In
|
||||
* that case, we highlight any row/column where the actually laid
|
||||
* tracks don't match the clue.
|
||||
*/
|
||||
pathret = ret; /* Do we have a plausible solution so far? */
|
||||
for (x = 0; x < w; x++) {
|
||||
target = state->numbers->numbers[x];
|
||||
ntrack = nnotrack = ntrackcomplete = 0;
|
||||
for (y = 0; y < h; y++) {
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) > 0 ||
|
||||
state->sflags[y*w+x] & S_TRACK)
|
||||
ntrack++;
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) == 2)
|
||||
ntrackcomplete++;
|
||||
if (state->sflags[y*w+x] & S_NOTRACK)
|
||||
nnotrack++;
|
||||
}
|
||||
if (mark) {
|
||||
if (ntrack > target || nnotrack > (h-target) ||
|
||||
(pathret && ntrackcomplete != target)) {
|
||||
debug(("col %d error: target %d, track %d, notrack %d, "
|
||||
"pathret %d, trackcomplete %d",
|
||||
x, target, ntrack, nnotrack, pathret, ntrackcomplete));
|
||||
state->num_errors[x] = 1;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (ntrackcomplete != target)
|
||||
ret = false;
|
||||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
target = state->numbers->numbers[w+y];
|
||||
ntrack = nnotrack = ntrackcomplete = 0;
|
||||
for (x = 0; x < w; x++) {
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) > 0 ||
|
||||
state->sflags[y*w+x] & S_TRACK)
|
||||
ntrack++;
|
||||
if (S_E_COUNT(state, x, y, E_TRACK) == 2)
|
||||
ntrackcomplete++;
|
||||
if (state->sflags[y*w+x] & S_NOTRACK)
|
||||
nnotrack++;
|
||||
}
|
||||
if (mark) {
|
||||
if (ntrack > target || nnotrack > (w-target) ||
|
||||
(pathret && ntrackcomplete != target)) {
|
||||
debug(("row %d error: target %d, track %d, notrack %d, "
|
||||
"pathret %d, trackcomplete %d",
|
||||
y, target, ntrack, nnotrack, pathret, ntrackcomplete));
|
||||
state->num_errors[w+y] = 1;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
if (ntrackcomplete != target)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (mark)
|
||||
state->completed = ret;
|
||||
sfree(dsf);
|
||||
|
Reference in New Issue
Block a user