Patch from Jonas Koelker to add keyboard control support to Pearl.
[sgt/puzzles] / bridges.c
index 694f011..6a677e3 100644 (file)
--- a/bridges.c
+++ b/bridges.c
@@ -513,7 +513,6 @@ static int island_impossible(struct island *is, int strict)
 {
     int curr = island_countbridges(is), nspc = is->count - curr, nsurrspc;
     int i, poss;
-    grid_type v;
     struct island *is_orth;
 
     if (nspc < 0) {
@@ -533,7 +532,6 @@ static int island_impossible(struct island *is, int strict)
         int ifree, dx = is->adj.points[i].dx;
 
         if (!is->adj.points[i].off) continue;
-        v = GRID(is->state, is->adj.points[i].x, is->adj.points[i].y);
         poss = POSSIBLES(is->state, dx,
                          is->adj.points[i].x, is->adj.points[i].y);
         if (poss == 0) continue;
@@ -542,9 +540,24 @@ static int island_impossible(struct island *is, int strict)
         assert(is_orth);
 
         ifree = is_orth->count - island_countbridges(is_orth);
-        if (ifree > 0)
-            nsurrspc += min(ifree, MAXIMUM(is->state, dx,
-                                           is->adj.points[i].x, is->adj.points[i].y));
+        if (ifree > 0) {
+           /*
+            * ifree is the number of bridges unfilled in the other
+            * island, which is clearly an upper bound on the number
+            * of extra bridges this island may run to it.
+            *
+            * Another upper bound is the number of bridges unfilled
+            * on the specific line between here and there. We must
+            * take the minimum of both.
+            */
+           int bmax = MAXIMUM(is->state, dx,
+                              is->adj.points[i].x, is->adj.points[i].y);
+           int bcurr = GRIDCOUNT(is->state,
+                                 is->adj.points[i].x, is->adj.points[i].y,
+                                 dx ? G_LINEH : G_LINEV);
+           assert(bcurr <= bmax);
+            nsurrspc += min(ifree, bmax - bcurr);
+       }
     }
     if (nsurrspc < nspc) {
         debug(("island at (%d,%d) impossible: surr. islands %d spc, need %d.\n",
@@ -1492,11 +1505,11 @@ static int solve_island_stage3(struct island *is, int *didsth_r)
             if (maxb == 0) {
                 debug(("...adding NOLINE.\n"));
                 solve_join(is, i, -1, 0); /* we can't have any bridges here. */
-                didsth = 1;
             } else {
                 debug(("...setting maximum\n"));
                 solve_join(is, i, maxb, 1);
             }
+            didsth = 1;
         }
         map_update_possibles(is->state);
     }
@@ -2244,6 +2257,8 @@ static game_state *execute_move(game_state *state, char *move)
             if (sscanf(move, "%d,%d,%d,%d,%d%n",
                        &x1, &y1, &x2, &y2, &nl, &n) != 5)
                 goto badmove;
+            if (!INGRID(ret, x1, y1) || !INGRID(ret, x2, y2))
+                goto badmove;
             is1 = INDEX(ret, gridi, x1, y1);
             is2 = INDEX(ret, gridi, x2, y2);
             if (!is1 || !is2) goto badmove;
@@ -2253,6 +2268,8 @@ static game_state *execute_move(game_state *state, char *move)
             if (sscanf(move, "%d,%d,%d,%d%n",
                        &x1, &y1, &x2, &y2, &n) != 4)
                 goto badmove;
+            if (!INGRID(ret, x1, y1) || !INGRID(ret, x2, y2))
+                goto badmove;
             is1 = INDEX(ret, gridi, x1, y1);
             is2 = INDEX(ret, gridi, x2, y2);
             if (!is1 || !is2) goto badmove;
@@ -2261,6 +2278,8 @@ static game_state *execute_move(game_state *state, char *move)
             if (sscanf(move, "%d,%d%n",
                        &x1, &y1, &n) != 2)
                 goto badmove;
+            if (!INGRID(ret, x1, y1))
+                goto badmove;
             is1 = INDEX(ret, gridi, x1, y1);
             if (!is1) goto badmove;
             island_togglemark(is1);
@@ -2473,7 +2492,7 @@ static void dsf_debug_draw(drawing *dr,
 #ifdef DRAW_DSF
     int ts = TILE_SIZE/2;
     int ox = COORD(x) + ts/2, oy = COORD(y) + ts/2;
-    char str[10];
+    char str[32];
 
     sprintf(str, "%d", dsf_canonify(state->solver->dsf, DINDEX(x,y)));
     draw_text(dr, ox, oy, FONT_VARIABLE, ts,
@@ -2550,7 +2569,7 @@ static void island_redraw(drawing *dr,
     int col = (v & G_ISSEL) ? COL_SELECTED : tcol;
     int bg = (v & G_CURSOR) ? COL_CURSOR :
         (v & G_MARK) ? COL_MARK : COL_BACKGROUND;
-    char str[10];
+    char str[32];
 
 #ifdef DRAW_GRID
     draw_rect_outline(dr, COORD(is->x), COORD(is->y),
@@ -2694,6 +2713,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)
 {
     return TRUE;
@@ -2714,7 +2738,7 @@ static void game_print(drawing *dr, game_state *state, int ts)
     int ink = print_mono_colour(dr, 0);
     int paper = print_mono_colour(dr, 1);
     int x, y, cx, cy, i, nl;
-    int loff = ts/8;
+    int loff;
     grid_type grid;
 
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
@@ -2724,6 +2748,7 @@ static void game_print(drawing *dr, game_state *state, int ts)
     /* I don't think this wants a border. */
 
     /* Bridges */
+    loff = ts / (8 * sqrt((state->params.maxb - 1)));
     print_line_width(dr, ts / 12);
     for (x = 0; x < state->w; x++) {
         for (y = 0; y < state->h; y++) {
@@ -2733,27 +2758,21 @@ static void game_print(drawing *dr, game_state *state, int ts)
 
             if (grid & G_ISLAND) continue;
             if (grid & G_LINEV) {
-                if (nl > 1) {
-                    draw_line(dr, cx+ts/2-loff, cy, cx+ts/2-loff, cy+ts, ink);
-                    draw_line(dr, cx+ts/2+loff, cy, cx+ts/2+loff, cy+ts, ink);
-                } else {
-                    draw_line(dr, cx+ts/2,      cy, cx+ts/2,      cy+ts, ink);
-                }
+                for (i = 0; i < nl; i++)
+                    draw_line(dr, cx+ts/2+(2*i-nl+1)*loff, cy,
+                              cx+ts/2+(2*i-nl+1)*loff, cy+ts, ink);
             }
             if (grid & G_LINEH) {
-                if (nl > 1) {
-                    draw_line(dr, cx, cy+ts/2-loff, cx+ts, cy+ts/2-loff, ink);
-                    draw_line(dr, cx, cy+ts/2+loff, cx+ts, cy+ts/2+loff, ink);
-                } else {
-                    draw_line(dr, cx, cy+ts/2,      cx+ts,      cy+ts/2, ink);
-                }
+                for (i = 0; i < nl; i++)
+                    draw_line(dr, cx, cy+ts/2+(2*i-nl+1)*loff,
+                              cx+ts, cy+ts/2+(2*i-nl+1)*loff, ink);
             }
         }
     }
 
     /* Islands */
     for (i = 0; i < state->n_islands; i++) {
-        char str[10];
+        char str[32];
         struct island *is = &state->islands[i];
         grid = GRID(state, is->x, is->y);
         cx = COORD(is->x) + ts/2;
@@ -2802,6 +2821,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,