char const *p = string;
ret->width = atoi(p);
- while (*p && isdigit(*p)) p++;
+ while (*p && isdigit((unsigned char)*p)) p++;
if (*p == 'x') {
p++;
ret->height = atoi(p);
- while (*p && isdigit(*p)) p++;
+ while (*p && isdigit((unsigned char)*p)) p++;
} else {
ret->height = ret->width;
}
} else if (*p == 'b') {
p++;
ret->barrier_probability = atof(p);
- while (*p && isdigit(*p)) p++;
+ while (*p && (*p == '.' || isdigit((unsigned char)*p))) p++;
} else if (*p == 'a') {
p++;
ret->unique = FALSE;
- }
+ } else
+ p++; /* skip any other gunk */
}
}
ret[len++] = 'w';
if (full && params->barrier_probability)
len += sprintf(ret+len, "b%g", params->barrier_probability);
- if (!params->unique)
+ if (full && !params->unique)
ret[len++] = 'a';
assert(len < lenof(ret));
ret[len] = '\0';
return ret;
}
-static int net_solver(int w, int h, unsigned char *tiles, int wrapping)
+static int net_solver(int w, int h, unsigned char *tiles,
+ unsigned char *barriers, int wrapping)
{
unsigned char *tilestate;
unsigned char *edgestate;
}
}
+ /*
+ * If we have barriers available, we can mark those edges as
+ * closed too.
+ */
+ if (barriers) {
+ for (y = 0; y < h; y++) for (x = 0; x < w; x++) {
+ int d;
+ for (d = 1; d <= 8; d += d) {
+ if (barriers[y*w+x] & d) {
+ int x2, y2;
+ /*
+ * In principle the barrier list should already
+ * contain each barrier from each side, but
+ * let's not take chances with our internal
+ * consistency.
+ */
+ OFFSETWH(x2, y2, x, y, d, w, h);
+ edgestate[(y*w+x) * 5 + d] = 2;
+ edgestate[(y2*w+x2) * 5 + F(d)] = 2;
+ }
+ }
+ }
+ }
+
/*
* Since most deductions made by this solver are local (the
* exception is loop avoidance, where joining two tiles
* dead ends of size 2 and 3 forms a subnetwork
* with a total area of 6, not 5.)
*/
- if (deadendtotal+1 < area)
+ if (deadendtotal > 0 && deadendtotal+1 < area)
valid = FALSE;
} else if (nnondeadends == 1) {
/*
assert(j > 0); /* we can't lose _all_ possibilities! */
if (j < i) {
- int a, o;
done_something = TRUE;
/*
*/
while (j < 4)
tilestate[(y*w+x) * 4 + j++] = 255;
+ }
- /*
- * Now go through them again and see if we've
- * deduced anything new about any edges.
- */
+ /*
+ * Now go through the tile orientations again and see
+ * if we've deduced anything new about any edges.
+ */
+ {
+ int a, o;
a = 0xF; o = 0;
+
for (i = 0; i < 4 && tilestate[(y*w+x) * 4 + i] != 255; i++) {
a &= tilestate[(y*w+x) * 4 + i];
o |= tilestate[(y*w+x) * 4 + i];
/*
* Run the solver to check unique solubility.
*/
- while (!net_solver(w, h, tiles, params->wrapping)) {
+ while (!net_solver(w, h, tiles, NULL, params->wrapping)) {
int n = 0;
/*
* not yield a complete solution.
*/
ret = dup_game(state);
- net_solver(ret->width, ret->height, ret->tiles, ret->wrapping);
+ net_solver(ret->width, ret->height, ret->tiles,
+ ret->barriers, ret->wrapping);
} else {
assert(aux->width == state->width);
assert(aux->height == state->height);