shithub: puzzles

Download patch

ref: 7011d13ae7a662d43238601a63a8992b71e19d56
parent: fabfc2caed8e5fa7391c133dd89db45a353e6b35
author: Simon Tatham <anakin@pobox.com>
date: Wed Feb 17 14:15:04 EST 2010

A proper fix from James H for the negative number issue: the
assertion I crudely commented out has now been replaced with code
that clearly shows what you did wrong in the failing situation.

[originally from svn r8872]

--- a/signpost.c
+++ b/signpost.c
@@ -916,7 +916,7 @@
 
 static int head_number(game_state *state, int i, int *scratch)
 {
-    int off = 0, start = -1, ss, j = i, c, n, sz;
+    int off = 0, found = 0, start, ss, j = i, c, n, sz;
     const char *why = NULL;
 
     assert(state->prev[i] == -1 && state->next[i] != -1);
@@ -926,11 +926,12 @@
     while (j != -1) {
         if (state->flags[j] & FLAG_IMMUTABLE) {
             ss = state->nums[j] - off;
-            if (start == -1) {
+            if (!found) {
                 start = ss;
+                found = 1;
                 why = "contains cell with immutable number";
             } else if (start != ss) {
-                debug(("head_number: chain with non-sequential numbers."));
+                debug(("head_number: chain with non-sequential numbers!"));
                 state->impossible = 1;
             }
         }
@@ -938,7 +939,7 @@
         j = state->next[j];
         assert(j != i); /* we have created a loop, obviously wrong */
     }
-    if (start != -1) goto found;
+    if (found) goto done;
 
     if (state->nums[i] == 0) {
         if (state->nums[state->next[i]] != 0) {
@@ -949,6 +950,7 @@
             start = lowest_start(state, scratch);
             why = "lowest available colour group";
         }
+        found = 1;
     } else {
         c = COLOUR(state->nums[i]);
         n = 1;
@@ -958,6 +960,7 @@
             j = state->next[j];
             if (state->nums[j] == 0) {
                 start = START(c);
+                found = 1;
                 why = "adding blank cell to end of numbered region";
                 break;
             }
@@ -972,14 +975,16 @@
                     start = START(c);
                     why = "joining two coloured regions, taking largest";
                 }
+                found = 1;
                 break;
             }
         }
         /* If we got here then we may have split a region into
          * two; make sure we don't assign a colour we've already used. */
-        if (start == -1) {
+        if (!found) {
             start = (c == 0) ? lowest_start(state, scratch) : START(c);
             why = "got to end of coloured region";
+            found = 1;
         }
         if (used_colour(state, i, start)) {
             start = lowest_start(state, scratch);
@@ -987,8 +992,8 @@
         }
     }
 
-found:
-    assert(start != -1 && why != NULL);
+done:
+    assert(found && why != NULL);
     debug(("Chain at (%d,%d) numbered at %d: %s.",
            i%state->w, i/state->w, start, why));
     return start;
@@ -1035,10 +1040,8 @@
     int i, j, nnum;
     int *scratch = snewn(state->n, int);
 
-    for (i = 0; i < state->n; i++) {
-        assert(state->nums[i] >= 0);
+    for (i = 0; i < state->n; i++)
         state->numsi[i] = -1;
-    }
 
     for (i = 0; i < state->n; i++) {
         if (state->flags[i] & FLAG_IMMUTABLE) {
@@ -1120,6 +1123,17 @@
         }
     }
 
+    /* Search and mark numbers less than 0, or 0 with links. */
+    for (n = 1; n < state->n; n++) {
+        if ((state->nums[n] < 0) ||
+            (state->nums[n] == 0 &&
+             (state->next[n] != -1 || state->prev[n] != -1))) {
+            error = 1;
+            if (mark_errors)
+                state->flags[n] |= FLAG_ERROR;
+        }
+    }
+
     if (error) return 0;
     return complete;
 }
@@ -1729,7 +1743,7 @@
 {
     int set = num / (ds->n+1);
 
-    if (num <= 0) return COL_BACKGROUND;
+    if (num <= 0) return COL_B0;
     return COL_B0 + (set % 16);
 }
 
@@ -1750,9 +1764,20 @@
     int cb = TILE_SIZE / 16, textsz;
     char buf[20];
     int arrowcol, sarrowcol, setcol, textcol;
-    int n = num % (ds->n+1), set = num / (ds->n+1);
-    int acx, acy, asz;
+    int acx, acy, asz, empty = 0;
 
+    if (num == 0 && !(f & F_ARROW_POINT) && !(f & F_ARROW_INPOINT)) {
+        empty = 1;
+        /*
+         * We don't display text in empty cells: typically these are
+         * signified by num=0. However, in some cases a cell could
+         * have had the number 0 assigned to it if the user made an
+         * error (e.g. tried to connect a chain of length 5 to the
+         * immutable number 4) so we _do_ display the 0 if the cell
+         * has a link in or a link out.
+         */
+    }
+
     /* Calculate colours. */
 
     if (print_ink >= 0) {
@@ -1763,7 +1788,7 @@
 	setcol = sarrowcol = -1;       /* placate optimiser */
     } else {
 
-	setcol = num2col(ds, num);
+	setcol = empty ? COL_BACKGROUND : num2col(ds, num);
 
 #define dim(fg,bg) ( \
       (bg)==COL_BACKGROUND ? COL_ARROW_BG_DIM : \
@@ -1833,11 +1858,14 @@
 
     /* Draw text (number or set). */
 
-    if (num != 0) {
-        /* assert(num > 0); - actually, no, this obstructs legal play */
-        if (set == 0) {
-            sprintf(buf, "%d", n);
+    if (!empty) {
+        int set = (num <= 0) ? 0 : num / (ds->n+1);
+
+        if (set == 0 || num <= 0) {
+            sprintf(buf, "%d", num);
         } else {
+            int n = num % (ds->n+1);
+
             if (n == 0)
                 sprintf(buf, "%c", (int)(set+'a'-1));
             else