RECREATING THE MATRIX RAIN WITH ANSI ESCAPE SEQUENCES

22 AUGUST 2022

Over the weekend, I came across Domsson’s Fakesteak: a beautifully lean rendition of the Matrix rain in raw C using ANSI escape sequences—zero dependencies, not even ncurses.

The project’s README noted that it didn’t support Japanese characters and that it used 8-bit color mode. The latter meant that the ghosting effect has to rely on different foreground colors rather than shades of the same color.

As a tip of the hat to Domsson’s impressive work, I decided to add Unicode and 24-bit truecolor support to it, aiming to faithfully recreate the original Matrix from the first movie during Neo and Cypher’s conversation:

Adding Unicode support via wchar_t and wprintf() was easy enough. Implementing the ghosting effect with truecolor support, however, turned out harder than expected. To achieve the ghosting effect, I treated phosphor decay as a multiplier, allowing me to emulate a dim afterglow by gradually transitioning each raindrop’s RGB values towards the background color:

static void mat_shade(matrix *mat, size_t row, size_t col) 
{
    unsigned char *color;
    color = mat->rgb[mat_idx(mat, row, col)].color;
    color[R] = color[R] - (color[R] - COLOR_BG_RED) / 2;
    color[G] = color[G] - (color[G] - COLOR_BG_GRN) / 2;
    color[B] = color[B] - (color[B] - COLOR_BG_BLU) / 2;
}

Looking back at the implementation, there are still a few improvements to be made. Instead of using a dedicated buffer, I should have bit-packed the phosphor decay into the RGB data buffer to save memory. I’m not entirely satisfied with the Unicode support as it’s restricted to contiguous code points. The glitch effect, which I implemented with characters unexpectedly changing, really should flash white as well.

Nonetheless, the rain closely resembles the original, is highly customizable, and is gentle on the CPU. Not too bad for a weekend project. I tested the program with xterm and urxvt terminal emulators on OpenBSD and Arch Linux systems. Someone has managed to get it moving on a Raspberry Pi as well.

Lastly, to compile and run:

$ cc -O3 main.c -o matrix
$ ./matrix

“All I see is blonde, brunette, red head.”

Files: source.tar.gz