diff --git a/tracks.c b/tracks.c index afb9ff9..a57ab0a 100644 --- a/tracks.c +++ b/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);