chiark / gitweb /
Automate creation of Bedbugs.rule
[bedbugs.git] / src / bedbugs.c
index f703ad673011086f42bb472c28dc8815e3202728..05d22ba39bb3ba41b11fd58d67b4f9f88a546373 100644 (file)
  * [...]
  */
 
+#include <assert.h>
+#include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -208,16 +210,12 @@ blackpixel(bool *r, int size, int bl, int br, int tr, int tl)
     }
 }
 
-int main(int argc, char *argv[])
+void bedstead (void)
 {
-
-        /* FIXME: output a complete rule file rather than a heap of
-         * fragments requiring manual assembly */
-
-        /* Bedbugs step 1: output smoothing rules as a Golly rule
-         * table mapping from (0,1) to an expanded set of states that
-         * we can hang icons from. (The smoothing algorithm requires
-         * a 3x3 neighbourhood, which is fortuitous.) */
+        /* Output smoothing rules as a Golly rule table mapping from
+         * (0,1) to an expanded set of states that we can hang icons
+         * from. (The smoothing algorithm requires a 3x3 neighbourhood,
+         * which is fortuitous.) */
 
         /* Index into small bitmap */
 #define GETPIX(x,y) (!!(iter & 1u<<((y)*3+(x))))
@@ -266,15 +264,26 @@ int main(int argc, char *argv[])
                                 /* Off states are 2..17 */
                                 state = 2 + (bl | br<<1 | tr<<2 | tl<<3);
                        }
+                        if (iter == 0) {
+                                /* Special case: we don't want to try to
+                                 * flip all of infinite empty space between
+                                 * 0 and 2 every step (this has odd effects
+                                 * on Golly) */
+                                assert(state == 2);
+                                state = 0;
+                        }
                         /* Output rule in Golly rule format
                          * (FIXME completely unoptimised) */
                         printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
                                GETPIX(x,y),U,UR,R,DR,D,DL,L,UL,state);
         }
+}
 
-        /* Bedbugs step 2: icons. In each size supported by Golly,
+void icons(void)
+{
+        /* Bedbugs icons. In each size supported by Golly,
          * draw one icon per state, in the XPM format Golly wants.
-         * This does not actually depend on step 1 at all.
+         * This does not actually depend on bedstead() at all.
          * (FIXME: but it could. Some of the states we generate icons
          * and rules for are not actually reachable. We could spot
          * unused states above and avoid generating icons or rules for
@@ -313,5 +322,50 @@ int main(int argc, char *argv[])
                 }
             }
         }
-        return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    while (!feof(stdin)) {
+        char l[100]; /* bleah */
+        if (!fgets(l, sizeof(l), stdin)) {
+            break;
+        }
+        if (strlen(l) == sizeof(l)-1) {
+            fprintf(stderr, "Long input line; possible truncation; I suck\n");
+            exit(1);
+        }
+        if (strlen(l) >= 2 && l[0] == '@' && l[1] == '@') {
+            size_t n = strcspn(l+2, "\n");
+            if (strncmp(l+2, "BEDSTEAD", n) == 0) {
+                bedstead();
+            } else if (strncmp(l+2, "ICONS", n) == 0) {
+                icons();
+            } else {
+                /* Bodily insert named file on stdout. */
+                FILE *f;
+                l[n+2]='\0';
+                if (!(f = fopen(l+2, "r"))) {
+                    fprintf(stderr, "Couldn't open '%s': %s\n", l+2,
+                            strerror(errno));
+                    exit(1);
+                } else {
+                    do {
+                        char buf[2048]; /* also bleah */
+                        size_t n = fread(buf, 1, sizeof(buf), f);
+                        fwrite(buf, 1, n, stdout);
+                    } while (!feof(f) && !ferror(f));
+                    if (ferror(f)) {
+                        fprintf(stderr, "Error reading '%s': %s\n", l+2,
+                                strerror(errno));
+                        exit(1);
+                    }
+                    fclose(f);
+                }
+            }
+        } else {
+            printf("%s", l);
+        }
+    }
+    return 0;
 }