Stop the analysis pass in Loopy's redraw routine from being
[sgt/puzzles] / keen.c
diff --git a/keen.c b/keen.c
index 8133183..5087465 100644 (file)
--- a/keen.c
+++ b/keen.c
@@ -281,8 +281,8 @@ static int solver_common(struct latin_solver *solver, void *vctx, int diff)
     for (box = 0; box < ctx->nboxes; box++) {
        int *sq = ctx->boxlist + ctx->boxes[box];
        int n = ctx->boxes[box+1] - ctx->boxes[box];
-       int value = ctx->clues[box] & ~CMASK;
-       int op = ctx->clues[box] & CMASK;
+       long value = ctx->clues[box] & ~CMASK;
+       long op = ctx->clues[box] & CMASK;
 
        if (diff == DIFF_HARD) {
            for (i = 0; i < n; i++)
@@ -887,13 +887,11 @@ done
         * suitable for what.
         */
 #define F_ADD     0x01
-#define F_ADD_BAD 0x02
-#define F_SUB     0x04
-#define F_SUB_BAD 0x08
-#define F_MUL     0x10
-#define F_MUL_BAD 0x20
-#define F_DIV     0x40
-#define F_DIV_BAD 0x80
+#define F_SUB     0x02
+#define F_MUL     0x04
+#define F_DIV     0x08
+#define BAD_SHIFT 4
+
        for (i = 0; i < a; i++) {
            singletons[i] = 0;
            j = dsf_canonify(dsf, i);
@@ -916,25 +914,23 @@ done
                v = p + q;
                if (v > 4 && v < 2*w-2)
                    singletons[j] |= F_ADD;
-               else
-                   singletons[j] |= F_ADD_BAD;
+                else
+                   singletons[j] |= F_ADD << BAD_SHIFT;
 
                /*
-                * Multiplication clues: similarly, we prefer clues
-                * of this type which leave multiple options open.
-                * We can't rule out all the others, though, because
-                * there are very very few 2-square multiplication
-                * clues that _don't_ leave only one option.
+                * Multiplication clues: above Normal difficulty, we
+                * prefer (but don't absolutely insist on) clues of
+                * this type which leave multiple options open.
                 */
                v = p * q;
                n = 0;
                for (k = 1; k <= w; k++)
                    if (v % k == 0 && v / k <= w && v / k != k)
                        n++;
-               if (n > 1)
+               if (n <= 2 && diff > DIFF_NORMAL)
+                   singletons[j] |= F_MUL << BAD_SHIFT;
+                else
                    singletons[j] |= F_MUL;
-               else
-                   singletons[j] |= F_MUL_BAD;
 
                /*
                 * Subtraction: we completely avoid a difference of
@@ -976,11 +972,10 @@ done
                long clue;
                int good, bad;
                switch (k) {
-                 case 0: clue = C_DIV; good = F_DIV; bad = F_DIV_BAD; break;
-                 case 1: clue = C_SUB; good = F_SUB; bad = F_SUB_BAD; break;
-                 case 2: clue = C_MUL; good = F_MUL; bad = F_MUL_BAD; break;
-                 default /* case 3 */ :
-                   clue = C_ADD; good = F_ADD; bad = F_ADD_BAD; break;
+                 case 0:                clue = C_DIV; good = F_DIV; break;
+                 case 1:                clue = C_SUB; good = F_SUB; break;
+                 case 2:                clue = C_MUL; good = F_MUL; break;
+                 default /* case 3 */ : clue = C_ADD; good = F_ADD; break;
                }
 
                for (i = 0; i < a; i++) {
@@ -993,9 +988,10 @@ done
                }
                if (i == a) {
                    /* didn't find a nice one, use a nasty one */
+                    bad = good << BAD_SHIFT;
                    for (i = 0; i < a; i++) {
                        j = order[i];
-                       if (singletons[j] & good) {
+                       if (singletons[j] & bad) {
                            clues[j] = clue;
                            singletons[j] = 0;
                            break;
@@ -1010,13 +1006,10 @@ done
                break;
        }
 #undef F_ADD
-#undef F_ADD_BAD
 #undef F_SUB
-#undef F_SUB_BAD
 #undef F_MUL
-#undef F_MUL_BAD
 #undef F_DIV
-#undef F_DIV_BAD
+#undef BAD_SHIFT
 
        /*
         * Having chosen the clue types, calculate the clue values.
@@ -1188,7 +1181,6 @@ static game_state *new_game(midend *me, game_params *params, char *desc)
 {
     int w = params->w, a = w*w;
     game_state *state = snew(game_state);
-    char *err;
     const char *p = desc;
     int i;
 
@@ -1197,7 +1189,7 @@ static game_state *new_game(midend *me, game_params *params, char *desc)
     state->clues->refcount = 1;
     state->clues->w = w;
     state->clues->dsf = snew_dsf(a);
-    err = parse_block_structure(&p, w, state->clues->dsf);
+    parse_block_structure(&p, w, state->clues->dsf);
 
     assert(*p == ',');
     p++;
@@ -1450,11 +1442,12 @@ static int check_errors(game_state *state, long *errors)
                break;
              case C_DIV:
                {
-                   int d1 = cluevals[j], d2 = state->grid[i];
-                   if (d1 == 0 || d2 == 0)
+                   int d1 = min(cluevals[j], state->grid[i]);
+                   int d2 = max(cluevals[j], state->grid[i]);
+                   if (d1 == 0 || d2 % d1 != 0)
                        cluevals[j] = 0;
                    else
-                       cluevals[j] = d2/d1 + d1/d2;/* one of them is 0 :-) */
+                       cluevals[j] = d2 / d1;
                }
                break;
            }
@@ -1519,7 +1512,7 @@ static int check_errors(game_state *state, long *errors)
     return errs;
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
+static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
                            int x, int y, int button)
 {
     int w = state->par.w;
@@ -1748,8 +1741,8 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
     sfree(ds);
 }
 
-void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
-              int x, int y, long tile)
+static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
+                     int x, int y, long tile)
 {
     int w = clues->w /* , a = w*w */;
     int tx, ty, tw, th;
@@ -1844,7 +1837,7 @@ void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
 
         /* Count the pencil marks required. */
         for (i = 1, npencil = 0; i <= w; i++)
-            if (tile & (1 << (i + DF_PENCIL_SHIFT)))
+            if (tile & (1L << (i + DF_PENCIL_SHIFT)))
                npencil++;
        if (npencil) {
 
@@ -1859,6 +1852,13 @@ void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
            pr = pl + TILESIZE - GRIDEXTRA;
            pt = ty + GRIDEXTRA;
            pb = pt + TILESIZE - GRIDEXTRA;
+           if (dsf_canonify(clues->dsf, y*w+x) == y*w+x) {
+               /*
+                * Make space for the clue text.
+                */
+               pt += TILESIZE/4;
+               /* minph--; */
+           }
 
            /*
             * We arrange our pencil marks in a grid layout, with
@@ -1914,7 +1914,7 @@ void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
             * Now actually draw the pencil marks.
             */
            for (i = 1, j = 0; i <= w; i++)
-               if (tile & (1 << (i + DF_PENCIL_SHIFT))) {
+               if (tile & (1L << (i + DF_PENCIL_SHIFT))) {
                    int dx = j % pw, dy = j / pw;
 
                    str[1] = '\0';
@@ -2005,6 +2005,11 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     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)
 {
     if (state->completed)
@@ -2240,6 +2245,10 @@ static void game_print(drawing *dr, game_state *state, int tilesize)
                          FONT_VARIABLE, TILESIZE/2,
                          ALIGN_VCENTRE | ALIGN_HCENTRE, ink, str);
            }
+
+    sfree(minus_sign);
+    sfree(times_sign);
+    sfree(divide_sign);
 }
 
 #ifdef COMBINED
@@ -2277,6 +2286,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,