ref: 99d3c31e12ac5bb7c12d2b7a59c702cb671e9b62
parent: 4ec2c580453b0629b9935cb1e90017de6d110608
author: Ben Harris <bjh21@bjh21.me.uk>
date: Tue Dec 27 11:14:48 EST 2022
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.
--- a/tracks.c
+++ b/tracks.c
@@ -1823,7 +1823,7 @@
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 @@
}
}
- /* 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);
@@ -1947,6 +1895,70 @@
* return true. */
ret = false;
}
+ }
+
+ /*
+ * 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)