Added option to increase pixel size in WolframAutomata from 1x1 to NxN as command...
authorAaron Taylor <ataylor@subgeniuskitty.com>
Sun, 14 Mar 2021 08:08:42 +0000 (00:08 -0800)
committerAaron Taylor <ataylor@subgeniuskitty.com>
Sun, 14 Mar 2021 08:08:42 +0000 (00:08 -0800)
Also cleaned up command-line option for the delay in microseconds between draw() calls.

hacks/WolframAutomata/WolframAutomata.c

index 6eb16fe..5349b1a 100644 (file)
@@ -51,14 +51,19 @@ struct state {
     size_t    num_generations;
 
     // TODO: Explain all of these.
     size_t    num_generations;
 
     // TODO: Explain all of these.
-    int delay_microsec; // per generation
     unsigned long fg, bg;
     int xlim, ylim, ypos; // explain roughly how and where we use these. Note: I'm not thrilled xlim/ylim since they are actually the width of the display, not the limit of the index (off by one). Change those names.
     Bool display_info;
     unsigned long fg, bg;
     int xlim, ylim, ypos; // explain roughly how and where we use these. Note: I'm not thrilled xlim/ylim since they are actually the width of the display, not the limit of the index (off by one). Change those names.
     Bool display_info;
-    // TODO: Add an option for 'pixel size', so the user can define 1x1 or 2x2 or 3x3 or ... pixels. But then I need to deal with leftover pixels.
 
     Bool * current_generation;
     uint8_t ruleset;
 
     Bool * current_generation;
     uint8_t ruleset;
+
+    /* Misc Commandline Options */
+    int pixel_size; /* Size of CA cell in pixels (e.g. pixel_size=3 means 3x3 pixels per cell). */
+    int delay_microsec; /* Requested delay to screenhack framework before next call to WolframAutomata_draw(). */
+
+    /* Expository Variables - Not strictly necessary, but makes some code easier to read. */
+    size_t number_of_cells;
 };
 
 static void *
 };
 
 static void *
@@ -80,24 +85,30 @@ WolframAutomata_init(Display * dpy, Window win)
     state->bg = gcv.background = get_pixel_resource(state->dpy, xgwa.colormap, "background", "Background");
     state->gc = XCreateGC(state->dpy, state->win, GCForeground, &gcv);
 
     state->bg = gcv.background = get_pixel_resource(state->dpy, xgwa.colormap, "background", "Background");
     state->gc = XCreateGC(state->dpy, state->win, GCForeground, &gcv);
 
-    state->delay_microsec = get_integer_resource(state->dpy, "delay", "Integer");
+    state->delay_microsec = get_integer_resource(state->dpy, "delay-usec", "Integer");
     if (state->delay_microsec < 0) state->delay_microsec = 0;
 
     if (state->delay_microsec < 0) state->delay_microsec = 0;
 
+    state->pixel_size = get_integer_resource(state->dpy, "pixel-size", "Integer");
+    if (state->pixel_size < 1) state->pixel_size = 1;
+    if (state->pixel_size > state->xlim) state->pixel_size = state->xlim;
+
+    state->number_of_cells = state->xlim / state->pixel_size;
+
     // TODO: These should be command-line options, but I need to learn how the get_integer_resource() and similar functions work first.
     state->display_info = True;
     state->ruleset = 30;
     // TODO: These should be command-line options, but I need to learn how the get_integer_resource() and similar functions work first.
     state->display_info = True;
     state->ruleset = 30;
-    state->num_generations = 10000; // TODO: Enforce that this is >1 in order to hold the seed generation and at least one pass through WolframAutomata_draw(), which is where we check for a full pixmap.
+    state->num_generations = 3000; // TODO: Enforce that this is >1 in order to hold the seed generation and at least one pass through WolframAutomata_draw(), which is where we check for a full pixmap.
 
 
-    state->current_generation = calloc(1, (sizeof(*(state->current_generation))*(state->xlim))); // TODO: Check calloc() call TODO: Can't recall precedence; can I eliminate any parenthesis?
+    state->current_generation = calloc(1, (sizeof(*(state->current_generation))*state->number_of_cells)); // TODO: Check calloc() call TODO: Can't recall precedence; can I eliminate any parenthesis?
     // TODO: Make the starting state a user-configurable option. At least give the user some options like 'random', 'one-middle', 'one edge', etc.
     //       Ideally accept something like a list of integers representing starting pixels to be "on".
     // TODO: Make the starting state a user-configurable option. At least give the user some options like 'random', 'one-middle', 'one edge', etc.
     //       Ideally accept something like a list of integers representing starting pixels to be "on".
-    state->current_generation[state->xlim-1] = True;
+    state->current_generation[0] = True;
 
 
-    state->evolution_history = XCreatePixmap(state->dpy, state->win, state->xlim, state->num_generations, xgwa.depth);
+    state->evolution_history = XCreatePixmap(state->dpy, state->win, state->xlim, state->num_generations*state->pixel_size, xgwa.depth);
     // Pixmap contents are undefined after creation. Explicitly set a black
     // background by drawing a black rectangle over the entire pixmap.
     XSetForeground(state->dpy, state->gc, state->bg);
     // Pixmap contents are undefined after creation. Explicitly set a black
     // background by drawing a black rectangle over the entire pixmap.
     XSetForeground(state->dpy, state->gc, state->bg);
-    XFillRectangle(state->dpy, state->evolution_history, state->gc, 0, 0, state->xlim, state->num_generations);
+    XFillRectangle(state->dpy, state->evolution_history, state->gc, 0, 0, state->xlim, state->num_generations*state->pixel_size);
     XSetForeground(state->dpy, state->gc, state->fg);
     // TODO: Need to draw starting generation on pixmap and increment state->ypos.
 
     XSetForeground(state->dpy, state->gc, state->fg);
     // TODO: Need to draw starting generation on pixmap and increment state->ypos.
 
@@ -110,10 +121,10 @@ size_t
 sindex(struct state * state, int index)
 {
     while (index < 0) {
 sindex(struct state * state, int index)
 {
     while (index < 0) {
-        index += state->xlim;
+        index += state->number_of_cells;
     }
     }
-    while (index >= state->xlim) {
-        index -= state->xlim;
+    while (index >= state->number_of_cells) {
+        index -= state->number_of_cells;
     }
     return (size_t) index;
 }
     }
     return (size_t) index;
 }
@@ -143,9 +154,9 @@ void
 render_current_generation(struct state * state)
 {
     size_t xpos;
 render_current_generation(struct state * state)
 {
     size_t xpos;
-    for (xpos = 0; xpos < state->xlim; xpos++) {
+    for (xpos = 0; xpos < state->number_of_cells; xpos++) {
         if (state->current_generation[xpos] == True) {
         if (state->current_generation[xpos] == True) {
-            XFillRectangle(state->dpy, state->evolution_history, state->gc, xpos, state->ypos, 1, 1);
+            XFillRectangle(state->dpy, state->evolution_history, state->gc, xpos*state->pixel_size, state->ypos, state->pixel_size, state->pixel_size);
         }
     }
 }
         }
     }
 }
@@ -166,10 +177,10 @@ WolframAutomata_draw(Display * dpy, Window win, void * closure)
     int window_y_offset;
 
     Bool new_generation[state->xlim];
     int window_y_offset;
 
     Bool new_generation[state->xlim];
-    for (xpos = 0; xpos < state->xlim; xpos++) {
+    for (xpos = 0; xpos < state->number_of_cells; xpos++) {
         new_generation[xpos] = calculate_cell(state, xpos);
     }
         new_generation[xpos] = calculate_cell(state, xpos);
     }
-    for (xpos = 0; xpos < state->xlim; xpos++) {
+    for (xpos = 0; xpos < state->number_of_cells; xpos++) {
         state->current_generation[xpos] = new_generation[xpos];
     }
     render_current_generation(state);
         state->current_generation[xpos] = new_generation[xpos];
     }
     render_current_generation(state);
@@ -177,11 +188,12 @@ WolframAutomata_draw(Display * dpy, Window win, void * closure)
     // Was this the final generation of this particular simulation? If so, give
     // the user a moment to bask in the glory of our output and then start a
     // new simulation.
     // Was this the final generation of this particular simulation? If so, give
     // the user a moment to bask in the glory of our output and then start a
     // new simulation.
-    if (state->ypos < state->num_generations-1) {
-        state->ypos++;
+    if (state->ypos/state->pixel_size < state->num_generations-1) {
+        state->ypos += state->pixel_size;
     } else {
         // TODO: Wait for a second or two, clear the screen and do a new iteration with suitably changed settings.
         // Note: Since we can't actually loop or sleep here, we need to add a flag to the state struct to indicate that we're in an 'admiration timewindow' (and indicate when it should end)
     } else {
         // TODO: Wait for a second or two, clear the screen and do a new iteration with suitably changed settings.
         // Note: Since we can't actually loop or sleep here, we need to add a flag to the state struct to indicate that we're in an 'admiration timewindow' (and indicate when it should end)
+        printf("infinite hamster wheel\n");
         while (1) continue;
     }
 
         while (1) continue;
     }
 
@@ -201,15 +213,19 @@ WolframAutomata_draw(Display * dpy, Window win, void * closure)
     return state->delay_microsec;
 }
 
     return state->delay_microsec;
 }
 
+// TODO: Fix formatting
 static const char * WolframAutomata_defaults[] = {
     ".background:    black",
     ".foreground:    white",
 static const char * WolframAutomata_defaults[] = {
     ".background:    black",
     ".foreground:    white",
-    "*delay:    2500",
+    "*delay-usec:    2500",
+    "*pixel-size:    1",  // TODO: Difference between dot and asterisk? Presumably the asterisk matches all resouces of attribute "pixelsize"?
     0
 };
 
     0
 };
 
+// TODO: Fix formatting
 static XrmOptionDescRec WolframAutomata_options[] = {
 static XrmOptionDescRec WolframAutomata_options[] = {
-    { "-delay",        ".delay",    XrmoptionSepArg, 0 },
+    { "-delay-usec",        ".delay-usec",    XrmoptionSepArg, 0 },
+    { "-pixel-size",    ".pixel-size",    XrmoptionSepArg, 0 },
     { 0, 0, 0, 0 }
 };
 
     { 0, 0, 0, 0 }
 };