From 80cfe219638914799dd0f4aef4a2840c20cf04ee Mon Sep 17 00:00:00 2001 From: Aaron Taylor Date: Sun, 14 Mar 2021 03:46:41 -0700 Subject: [PATCH] Added CLI options for requesting a specific rule, random rules, or random curated rules in WolframAutomata. Also bumped up the default delay by 10x. --- hacks/WolframAutomata/WolframAutomata.c | 65 ++++++++++++++++++++----- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/hacks/WolframAutomata/WolframAutomata.c b/hacks/WolframAutomata/WolframAutomata.c index 1327532..33182e1 100644 --- a/hacks/WolframAutomata/WolframAutomata.c +++ b/hacks/WolframAutomata/WolframAutomata.c @@ -29,9 +29,10 @@ // display info overlay with CA number and start conditions? // -overlay // which ruleset number to use? Or random? Or random from small set of hand-selected interesting examples? -// Options (with precedence): -rule N -// -rule-curated -// -rule-random +// In order of precedence: +// -random (select a random rule on each run) +// -rule N (always simulate Rule N on each run) +// (if neither of the above two are specified, then a random CURATED rule is selected on each run) // which starting population to use? Or random? Or one bit in middle? Or one bit on edge? (For random: Can I allow specifying a density like 25%, 50%, 75%?) // Options (with precedence): -population STRING (string is a comma separated list of cell IDs to populate, starting from 0) // -population-curated @@ -54,7 +55,11 @@ struct state { Bool display_info; Bool * current_generation; - uint8_t ruleset; + + // TODO: Describe these. + uint8_t rule_number; // Note: This is not a CLI option. You're thinking of rule_requested. + uint8_t rule_requested; // Note: Repurposing Rule 0 as a null value. + Bool rule_random; /* Misc Commandline Options */ int pixel_size; /* Size of CA cell in pixels (e.g. pixel_size=3 means 3x3 pixels per cell). */ @@ -65,6 +70,16 @@ struct state { size_t number_of_cells; }; +// TODO: Check the full set of 256 CAs for visually interesting examples. +static const uint8_t curated_rule_list[] = { + 22, + 30, + 45, + 57, + 73, + 86 +}; + static void * WolframAutomata_init(Display * dpy, Window win) { @@ -93,18 +108,38 @@ WolframAutomata_init(Display * dpy, Window win) state->number_of_cells = state->xlim / state->pixel_size; - /* - * The minimum number of generations is 2 since we must allocate enough - * space to hold the seed generation and at least one pass through - * WolframAutomata_draw(), which is where we check whether or not we've - * reached the end of the pixmap. - */ + /* The minimum number of generations is 2 since we must allocate enough */ + /* space to hold the seed generation and at least one pass through */ + /* WolframAutomata_draw(), which is where we check whether or not we've */ + /* reached the end of the pixmap. */ state->num_generations = get_integer_resource(state->dpy, "num-generations", "Integer"); if (state->num_generations < 0) state->num_generations = 2; + /* Time to figure out which rule to use for this simulation. */ + /* We ignore any weirdness resulting from the following cast since every */ + /* bit pattern is also a valid rule; if the user provides weird input, */ + /* then we'll return weird (but well-defined!) output. */ + state->rule_requested = (uint8_t) get_integer_resource(state->dpy, "rule-requested", "Integer"); + state->rule_random = get_boolean_resource(state->dpy, "rule-random", "Boolean"); + /* Through the following set of branches, we enforce CLI flag precedence. */ + if (state->rule_random) { + /* If this flag is set, the user wants truly random rules rather than */ + /* random rules from a curated list. */ + state->rule_number = (uint8_t) random(); + } else if (state->rule_requested != 0) { + /* Rule 0 is terribly uninteresting, so we are reusing it as a 'null' */ + /* value and hoping nobody notices. Finding a non-zero value means */ + /* the user requested a specific rule. Use it. */ + state->rule_number = state->rule_requested; + } else { + /* No command-line options were specified, so select rules randomly */ + /* from a curated list. */ + size_t number_of_array_elements = sizeof(curated_rule_list)/sizeof(curated_rule_list[0]); + state->rule_number = curated_rule_list[random() % number_of_array_elements]; + } + // 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->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. @@ -149,7 +184,7 @@ calculate_cell(struct state * state, int cell_id) cell_pattern |= 1; } } - if ((state->ruleset >> cell_pattern) & 1) { + if ((state->rule_number >> cell_pattern) & 1) { return True; } else { return False; @@ -224,10 +259,12 @@ WolframAutomata_draw(Display * dpy, Window win, void * closure) static const char * WolframAutomata_defaults[] = { ".background: black", ".foreground: white", - "*delay-usec: 2500", + "*delay-usec: 25000", // TODO: Difference between dot and asterisk? Presumably the asterisk matches all resouces of attribute "pixelsize"? Apply answer to all new options. "*pixel-size: 2", "*num-generations: 5000", + "*rule-requested: 0", + "*rule-random: False", 0 }; @@ -236,6 +273,8 @@ static XrmOptionDescRec WolframAutomata_options[] = { { "-delay-usec", ".delay-usec", XrmoptionSepArg, 0 }, { "-pixel-size", ".pixel-size", XrmoptionSepArg, 0 }, { "-num-generations", ".num-generations", XrmoptionSepArg, 0 }, + { "-rule", ".rule-requested", XrmoptionSepArg, 0 }, + { "-rule-random", ".rule-random", XrmoptionNoArg, "True" }, { 0, 0, 0, 0 } }; -- 2.20.1