shithub: puzzles

Download patch

ref: ad2fb760fc881d1ceb1ac1151bf60b85deb16c71
parent: bf9abb2a127a4a81babe50ecb419527f8aeffe28
author: Ben Harris <bjh21@bjh21.me.uk>
date: Fri Feb 10 13:28:36 EST 2023

Forbid game descriptions with joined islands in Bridges

A game description with islands in adjacent grid squares, like
"3x3:11g", shouldn't be allowed.  If it is, then bridges between the
islands are invisible and clicking one of them causes an assertion
failure: "Assertion `is_loop->adj.points[j].off > 1' failed."

The code to check this is really rather complex, but I think the
complexity is mostly necessary.

--- a/bridges.c
+++ b/bridges.c
@@ -2007,21 +2007,34 @@
 
 static const char *validate_desc(const game_params *params, const char *desc)
 {
-    int i, wh = params->w * params->h, nislands = 0;
+    int i, j, wh = params->w * params->h, nislands = 0;
+    bool *last_row = snewn(params->w, bool);
 
+    memset(last_row, 0, params->w * sizeof(bool));
     for (i = 0; i < wh; i++) {
-        if (*desc >= '1' && *desc <= '9')
+        if ((*desc >= '1' && *desc <= '9') || (*desc >= 'A' && *desc <= 'G')) {
             nislands++;
-        else if (*desc >= 'a' && *desc <= 'z')
+            /* Look for other islands to the left and above. */
+            if ((i % params->w > 0 && last_row[i % params->w - 1]) ||
+                last_row[i % params->w]) {
+                sfree(last_row);
+                return "Game description contains joined islands";
+            }
+            last_row[i % params->w] = true;
+        } else if (*desc >= 'a' && *desc <= 'z') {
+            for (j = 0; j < *desc - 'a' + 1; j++)
+                last_row[(i + j) % params->w] = false;
             i += *desc - 'a'; /* plus the i++ */
-        else if (*desc >= 'A' && *desc <= 'G')
-            nislands++;
-        else if (!*desc)
+        } else if (!*desc) {
+            sfree(last_row);
             return "Game description shorter than expected";
-        else
+        } else {
+            sfree(last_row);
             return "Game description contains unexpected character";
+        }
         desc++;
     }
+    sfree(last_row);
     if (*desc || i > wh)
         return "Game description longer than expected";
     if (nislands < 2)