Fixed decoding bug for dual grids
[sgt/puzzles] / pattern.c
index 787e591..043c1de 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -339,6 +339,10 @@ static int compute_rowdata(int *ret, unsigned char *start, int len, int step)
 #define DOT 2
 #define STILL_UNKNOWN 3
 
+#ifdef STANDALONE_SOLVER
+int verbose = FALSE;
+#endif
+
 static void do_recurse(unsigned char *known, unsigned char *deduced,
                        unsigned char *row, int *data, int len,
                        int freespace, int ndone, int lowest)
@@ -367,7 +371,11 @@ static void do_recurse(unsigned char *known, unsigned char *deduced,
 
 static int do_row(unsigned char *known, unsigned char *deduced,
                   unsigned char *row,
-                  unsigned char *start, int len, int step, int *data)
+                  unsigned char *start, int len, int step, int *data
+#ifdef STANDALONE_SOLVER
+                 , const char *rowcol, int index, int cluewid
+#endif
+                 )
 {
     int rowlen, i, freespace, done_any;
 
@@ -387,6 +395,27 @@ static int do_row(unsigned char *known, unsigned char *deduced,
            start[i*step] = deduced[i];
            done_any = TRUE;
        }
+#ifdef STANDALONE_SOLVER
+    if (verbose && done_any) {
+       char buf[80];
+       int thiscluewid;
+       printf("%s %2d: [", rowcol, index);
+       for (thiscluewid = -1, i = 0; data[i]; i++)
+           thiscluewid += sprintf(buf, " %d", data[i]);
+       printf("%*s", cluewid - thiscluewid, "");
+       for (i = 0; data[i]; i++)
+           printf(" %d", data[i]);
+       printf(" ] ");
+       for (i = 0; i < len; i++)
+           putchar(known[i] == BLOCK ? '#' :
+                   known[i] == DOT ? '.' : '?');
+       printf(" -> ");
+       for (i = 0; i < len; i++)
+           putchar(start[i*step] == BLOCK ? '#' :
+                   start[i*step] == DOT ? '.' : '?');
+       putchar('\n');
+    }
+#endif
     return done_any;
 }
 
@@ -444,12 +473,20 @@ static unsigned char *generate_soluble(random_state *rs, int w, int h)
             for (i=0; i<h; i++) {
                 rowdata[compute_rowdata(rowdata, grid+i*w, w, 1)] = 0;
                 done_any |= do_row(workspace, workspace+max, workspace+2*max,
-                                   matrix+i*w, w, 1, rowdata);
+                                   matrix+i*w, w, 1, rowdata
+#ifdef STANDALONE_SOLVER
+                                  , NULL, 0, 0 /* never do diagnostics here */
+#endif
+                                  );
             }
             for (i=0; i<w; i++) {
                 rowdata[compute_rowdata(rowdata, grid+i, h, w)] = 0;
                 done_any |= do_row(workspace, workspace+max, workspace+2*max,
-                                   matrix+i, h, w, rowdata);
+                                   matrix+i, h, w, rowdata
+#ifdef STANDALONE_SOLVER
+                                  , NULL, 0, 0 /* never do diagnostics here */
+#endif
+                                  );
             }
         } while (done_any);
 
@@ -569,7 +606,7 @@ static char *validate_desc(game_params *params, char *desc)
         if (*desc && isdigit((unsigned char)*desc)) {
             do {
                 p = desc;
-                while (desc && isdigit((unsigned char)*desc)) desc++;
+                while (*desc && isdigit((unsigned char)*desc)) desc++;
                 n = atoi(p);
                 rowspace -= n+1;
 
@@ -620,7 +657,7 @@ static game_state *new_game(midend *me, game_params *params, char *desc)
         if (*desc && isdigit((unsigned char)*desc)) {
             do {
                 p = desc;
-                while (desc && isdigit((unsigned char)*desc)) desc++;
+                while (*desc && isdigit((unsigned char)*desc)) desc++;
                 state->rowdata[state->rowsize * i + state->rowlen[i]++] =
                     atoi(p);
             } while (*desc++ == '.');
@@ -695,13 +732,21 @@ static char *solve_game(game_state *state, game_state *currstate,
                    max*sizeof(int));
             rowdata[state->rowlen[w+i]] = 0;
             done_any |= do_row(workspace, workspace+max, workspace+2*max,
-                               matrix+i*w, w, 1, rowdata);
+                               matrix+i*w, w, 1, rowdata
+#ifdef STANDALONE_SOLVER
+                              , NULL, 0, 0 /* never do diagnostics here */
+#endif
+                              );
         }
         for (i=0; i<w; i++) {
             memcpy(rowdata, state->rowdata + state->rowsize*i, max*sizeof(int));
             rowdata[state->rowlen[i]] = 0;
             done_any |= do_row(workspace, workspace+max, workspace+2*max,
-                               matrix+i, h, w, rowdata);
+                               matrix+i, h, w, rowdata
+#ifdef STANDALONE_SOLVER
+                              , NULL, 0, 0 /* never do diagnostics here */
+#endif
+                              );
         }
     } while (done_any);
 
@@ -808,7 +853,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
             ui->drag = LEFT_DRAG;
             ui->release = LEFT_RELEASE;
 #ifdef STYLUS_BASED
-            ui->state = currstate == GRID_FULL ? GRID_UNKNOWN : GRID_FULL;
+            ui->state = (currstate + 2) % 3; /* FULL -> EMPTY -> UNKNOWN */
 #else
             ui->state = GRID_FULL;
 #endif
@@ -816,7 +861,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
             ui->drag = RIGHT_DRAG;
             ui->release = RIGHT_RELEASE;
 #ifdef STYLUS_BASED
-            ui->state = currstate == GRID_EMPTY ? GRID_UNKNOWN : GRID_EMPTY;
+            ui->state = (currstate + 1) % 3; /* EMPTY -> FULL -> UNKNOWN */
 #else
             ui->state = GRID_EMPTY;
 #endif
@@ -1045,6 +1090,7 @@ static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
     ds->visible = snewn(ds->w * ds->h, unsigned char);
     ds->tilesize = 0;                  /* not decided yet */
     memset(ds->visible, 255, ds->w * ds->h);
+    ds->cur_x = ds->cur_y = 0;
 
     return ds;
 }
@@ -1236,6 +1282,11 @@ static float game_flash_length(game_state *oldstate,
     return 0.0F;
 }
 
+static int game_status(game_state *state)
+{
+    return state->completed ? +1 : 0;
+}
+
 static int game_timing_state(game_state *state, game_ui *ui)
 {
     return TRUE;
@@ -1340,6 +1391,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
@@ -1357,8 +1409,12 @@ int main(int argc, char **argv)
     while (--argc > 0) {
         char *p = *++argv;
        if (*p == '-') {
-            fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
-            return 1;
+           if (!strcmp(p, "-v")) {
+               verbose = TRUE;
+           } else {
+               fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
+               return 1;
+           }
         } else {
             id = p;
         }
@@ -1386,7 +1442,7 @@ int main(int argc, char **argv)
     s = new_game(NULL, p, desc);
 
     {
-       int w = p->w, h = p->h, i, j, done_any, max;
+       int w = p->w, h = p->h, i, j, done_any, max, cluewid = 0;
        unsigned char *matrix, *workspace;
        int *rowdata;
 
@@ -1397,6 +1453,22 @@ int main(int argc, char **argv)
 
         memset(matrix, 0, w*h);
 
+       if (verbose) {
+           int thiswid;
+           /*
+            * Work out the maximum text width of the clue numbers
+            * in a row or column, so we can print the solver's
+            * working in a nicely lined up way.
+            */
+           for (i = 0; i < (w+h); i++) {
+               char buf[80];
+               for (thiswid = -1, j = 0; j < s->rowlen[i]; j++)
+                   thiswid += sprintf(buf, " %d", s->rowdata[s->rowsize*i+j]);
+               if (cluewid < thiswid)
+                   cluewid = thiswid;
+           }
+       }
+
         do {
             done_any = 0;
             for (i=0; i<h; i++) {
@@ -1404,13 +1476,21 @@ int main(int argc, char **argv)
                       max*sizeof(int));
                rowdata[s->rowlen[w+i]] = 0;
                 done_any |= do_row(workspace, workspace+max, workspace+2*max,
-                                   matrix+i*w, w, 1, rowdata);
+                                   matrix+i*w, w, 1, rowdata
+#ifdef STANDALONE_SOLVER
+                                  , "row", i+1, cluewid
+#endif
+                                  );
             }
             for (i=0; i<w; i++) {
                memcpy(rowdata, s->rowdata + s->rowsize*i, max*sizeof(int));
                rowdata[s->rowlen[i]] = 0;
                 done_any |= do_row(workspace, workspace+max, workspace+2*max,
-                                   matrix+i, h, w, rowdata);
+                                   matrix+i, h, w, rowdata
+#ifdef STANDALONE_SOLVER
+                                  , "col", i+1, cluewid
+#endif
+                                  );
             }
         } while (done_any);