chiark / gitweb /
Pattern: randomise rounding bias in generate().
authorSimon Tatham <anakin@pobox.com>
Sat, 23 Sep 2017 18:22:37 +0000 (19:22 +0100)
committerSimon Tatham <anakin@pobox.com>
Sat, 23 Sep 2017 18:24:16 +0000 (19:24 +0100)
Now, with an odd grid size, we choose the posterisation threshold so
that half the time it delivers ceil(n/2) black squares and half the
time it delivers floor(n/2). Previously it only did the former, which
meant that asking Pattern to generate a 1x1 puzzle (with the bug in
the previous commit fixed) would always generate the one with a single
black square, and never the one with a single white square. Both are
trivial to solve, of course, but it seemed inelegant!

No change to the number of black squares in the puzzle solution can
constitute a spoiler for the player, of course, because that number is
trivial to determine without doing any difficult reasoning, just by
adding up all the clues in one dimension.

pattern.c

index ece1ed476e562913941b64b6d74409a35a91e9d7..e5f958abb817a600f10b1f9985ca2fd095380b7c 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -308,7 +308,18 @@ static void generate(random_state *rs, int w, int h, unsigned char *retgrid)
     fgrid2 = snewn(w*h, float);
     memcpy(fgrid2, fgrid, w*h*sizeof(float));
     qsort(fgrid2, w*h, sizeof(float), float_compare);
-    threshold = fgrid2[w*h/2];
+    /* Choose a threshold that makes half the pixels black. In case of
+     * an odd number of pixels, select randomly between just under and
+     * just over half. */
+    {
+        int index = w * h / 2;
+        if (w & h & 1)
+            index += random_upto(rs, 2);
+        if (index < w*h)
+            threshold = fgrid2[index];
+        else
+            threshold = fgrid2[w*h-1] + 1;
+    }
     sfree(fgrid2);
 
     for (i = 0; i < h; i++) {