# Code for Task #1 - Random Random Roger Roger!

**URL:** <https://forum.electromage.com/t/code-for-task-1-random-random-roger-roger/952>\
**Category:** Pixelblaze Academy of Wizardry and Enchantment\
**Created:** [January 30, 2021, 11:47pm UTC](https://forum.electromage.com/t/code-for-task-1-random-random-roger-roger/952 "2021-01-30T23:47:12Z")\
**Posts on this page:** 1\
**Showing post:** 8

<div class="post-metadata">

**Author:** ![zranger1](https://forum.electromage.com/user_avatar/forum.electromage.com/zranger1/32/301_2.png) [@zranger1](https://forum.electromage.com/u/zranger1)\
**Post date:** [February 6, 2021, 6:41pm UTC](https://forum.electromage.com/t/code-for-task-1-random-random-roger-roger/952/8 "2021-02-06T18:41:33Z")

</div>

In early, because it looks like I’m going to be stuck working on a plumbing repair the rest of the day. Thanks @scruffynerf for running this show – I’m already looking forward to next week’s installment!

Today, you will see elegant, compact and efficient code for this job. Then, there’s this. @jeff put the idea in my head - the only way to get rid of it was to write the code. It uses… yes, the center column from a cellular automaton running Wolfram’s Rule 30 to generate a stream of random bits, with which I control all the blinking lights. Without, further ado, here it is:

```auto
/*
  Rule 30 Flasher
  https://en.wikipedia.org/wiki/Rule_30 
  
  Flashes a random pixel for a random length of time, with a random amount of twinkling.
  
  Uses a 1D cellular automaton running Wolfram's rule 30 to generate a stream
  of random bits, which we use to build various random numbers.
  
  This pattern looks random, but for a given set of initial conditions, it's actually
  completely deterministic -- it'll be the same every time. 
*/

// arrays to hold the state of the current and previous generations of our
// automaton.
var ca_size = 32; // number of cells per generation
var ca_center = floor(ca_size / 2); // index center cell -- precalculates because we use it often

var g0 = array(ca_size);  
var g1 = array(ca_size);

// pointers to data arrays, so we can swap arrays by just swapping pointers
// instead of moving data.
var currState = g0;
var nextState = g1;  

var elapsedTime = 0; // accumulator for timing pixel displays
var lifetime = 500; // how long (ms) the current pixel will be displayed
var pix,hue,bri; // pixel index, color and current brightness

// Get random fraction of specified length from rule 30 generator
function getRandomFraction(n) {
  return result = getRandomBits(n) >> n
}

// return the specified number of random bits into a 32-bit buffer
// (will discard oldest bits if n > 32)
function getRandomBits(n) {
  var result = 0;
  
  for (i = 0; i < n; i++) {
    calcNextGen();    
    result = result << 1;
    result |= currState[ca_center];
  }
  return result;
}

// set up the CA mechanics
function initialize() {

// set up pointers to our data array.
  currState = g0;
  nextState = g1;  

// seed the cell at the center of the array. Bits in this
// column are reliably random, so it's where we'll get our
// random bits while running.
  currState[ca_center] = 1;
}

// Use the current state and Wolfram's Rule 30 to calculate the CA's next
// generation. Rule 30 generates very chaotic patterns, and the
// center column of the pattern is known to be a reasonably good RNG.
function calcNextGen() {
  var left,curr,right;

// set up 8-bit representation of current cell state. Note that "neighborhood"
// wraps around the ends of the array.
  for (var i = 0; i < ca_size; i++) {
    left = currState[(i > 0) ? i - 1 : ca_size - 1] << 2;
    curr = currState[i] << 1;
    right = currState[(i + 1) % ca_size];
    
// apply transformation rule
    nextState[i] = (30 & (1 << (left | curr | right))) > 0;
  }

// swap state arrays so the data for the generation we just calculated is in
// currState, which we will use to make random things happen.
  var a = currState; currState = nextState; nextState = a;  
}

// Main entry point - set up the CA before we start drawing pixels
initialize();

export function beforeRender(delta) {
  elapsedTime += delta;

// display timer -- accumulate deltas, generate new pixel when
// total time has reached or exceeded this pixel's random
// lifetime
  if (elapsedTime >= lifetime) {

// 8 bits will generate 256 distinct hues.     
    hue = getRandomFraction(8);    
    
// pixels will live for from 100 to 1200 ms   
    lifetime = 100+(1100*getRandomFraction(8));
    
// pick a random pixel. 11 bits will generate 2k unique indices. If your
// strip has more than 2k LEDs, not all pixels will be hit, but the indices
// will still be distributed over the whole strip.
    pix = floor(pixelCount * getRandomFraction(11)); 
    
// reset timer for the new pixel    
    elapsedTime = 0;  
  }
  
// calculate fadeout and twinkle, then adjust gamma.
// twinkle is controlled by grabbing a random bit from the CA on every frame
  bri = 1-((elapsedTime / lifetime)+(0.1 * getRandomBits(1)));
  bri = bri * bri;
}

// draw current pixel.Fadeout is a function of the random lifetime calculated
// in beforeRender, random twinkling is generated by varying saturation according to a bitstream
// from the CA 
export function render(index) {
  hsv(hue,1,(pix == index) * bri)
}

```

> **[Rube Goldberg machine](https://en.wikipedia.org/wiki/Rube_Goldberg_machine)**
>
> A Rube Goldberg machine, named after American cartoonist Rube Goldberg, is a chain reaction-type machine or contraption intentionally designed to perform a simple task in an indirect and overly complicated way. Usually, these machines consist of a series of simple unrelated devices; the action of each triggers the initiation of the next, eventually resulting in achieving a stated goal. In the United Kingdom, a similar contrivance is referred to as a "Heath Robinson contraption" after cartoons by ...

---

_[View the full topic](https://forum.electromage.com/t/code-for-task-1-random-random-roger-roger/952)._
