Simulating candle flickering with a simple RNG

While preparing to attach the electrical candles to the christmas tree, a question popped into my mind.

There are electrical candles that simulate the flickering of real candles. How complex would an algorithm have to be to be convincing?

I wrote a quick proof of concept in Ruby for a script running in the terminal which just randomly chooses a grey value to display.

#!/usr/bin/env ruby
require 'io/console'
lines, cols = $stdout.winsize

rnd = 0
loop {
  rnd = (rnd * 5 + 17) % 256
  lines.times {
    puts "\e[48;2;#{rnd};#{rnd};#{rnd}m" + (" " * cols) + "\e[0m"
  }
  sleep(0.11)
}

It uses a simple linear congruential generator as random number generator with a period of 256. This period is already large enough for the repetition to be not noticeable for a human being.

But there were obvious improvements, like using a better color and smoothing the transition from one color to the next.

I think given its simplicity it already works quite well. But the color transitions are quite harsh so for the second version I restricted the color value range, varied only one color channel, and added some ASCII art.

  function updateFlameColor() {
    rnd = (rnd * 5 + 17) % 256;

    // mapping the random value onto a color range from yellow to orange
    const r = 255;
    const g = 100 + rnd / 2; // 100..228
    const b = 0;

    flameEl.style.color = `rgb(${r},${g},${b})`;

    setTimeout(updateFlameColor, 110);
  }

This results in this cozy animation:

O
|
===