THE MATRIX DIGITAL RAIN
12 JANUARY 2024
“All I see is blonde, brunette, red head.” The iconic digital rain from The
Matrix implemented in C without dependencies (not even ncurses).
Overview
This is my fork of Domsson’s beautiful Fakesteak. As I was going through the fakesteak
code, I thought about what it might take to recreate the original rain from the
first Matrix movie without losing the program’s minimalism and elegance.
My version of the matrix has the following features:
- Unicode characters.
- Fully customizable 24-bit RGB (truecolor) colors.
- Glitches in the matrix.
- Ghosting effect of old monochrome displays.
- Closely resembles the one seen in the background while Neo and Cypher were
talking in the first Matrix movie.
As there are no dependencies, you can compile and run it however you want:
$ cc -O3 main.c -o matrix
$ ./matrix
How does it work?
The matrix struct makes use of two 2D arrays to encode the Matrix: the code
array for 32-bit Unicode characters and the rgb array for RGB values of the
characters (foreground color). The dimensions of these arrays depend on the
size of the terminal window. Each slot in the array corresponds to a cursor
position on the screen.
The ghosting effect, which is arguably the crowning feature of my version, is
implemented by carefully scaling and mixing the RGB channels:
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;
}
The above algorithm achieves transparency by iteratively bringing the
foreground color closer to the background color with each pass of the rain.
This approach offers multiple advantages, such as simpler and more natural
color configuration (background, foreground, and the color of the first drop)
that lends itself well to Unix ricing, and of course, recreates The Matrix rain
with high fidelity.
Rather than heavy-weight graphics tool kits, we use ANSI escape codes to
control the terminal screen. It’s the effective use of the ANSI escape codes
that greatly contributes to the minimalism of the solution:
static void term_print(const matrix *mat, size_t row, size_t col)
{
size_t idx;
idx = mat_idx(mat, row, col);
wprintf(L"\x1b[%d;%dH\x1b[38;2;%d;%d;%dm%lc",
row, col,
mat->rgb[idx].color[R],
mat->rgb[idx].color[G],
mat->rgb[idx].color[B],
mat->code[idx]);
}
Finally, the glitch effect is controlled by the following code:
if (mat.row[i] > 0 && rand() % 6 == 0) {
j = rand() % mat.row[i];
if (mat.code[mat_idx(&mat, j, mat.col[i])] != ' ') {
mat_put_code(&mat, j, mat.col[i]);
term_print(&mat, j, mat.col[i]);
}
}
The above code causes glitches in the Matrix with a probablity of 1/6.
Customizing the rain
While you can customize almost any aspect of the rain including its speed,
glitch frequency, and the density of the rain, the most useful settings for
ricing are the color scheme and the character set used for the rain.
There are three color settings: the head, the tail, and the background. They
are configured by setting the COLOR_*_RED, COLOR_*_GRN, and COLOR_*_BLU
definitions in main.c. The UNICODE_MIN and UNICODE_MAX values control the
Unicode block used. For instance, setting them to 0x30A1 and 0x30F6 rains
Katakana code points:

Files: source.tar.gz
“All I see is blonde, brunette, red head.” The iconic digital rain from The Matrix implemented in C without dependencies (not even ncurses).
Overview
This is my fork of Domsson’s beautiful Fakesteak. As I was going through the fakesteak code, I thought about what it might take to recreate the original rain from the first Matrix movie without losing the program’s minimalism and elegance.
My version of the matrix has the following features:
- Unicode characters.
- Fully customizable 24-bit RGB (truecolor) colors.
- Glitches in the matrix.
- Ghosting effect of old monochrome displays.
- Closely resembles the one seen in the background while Neo and Cypher were talking in the first Matrix movie.
As there are no dependencies, you can compile and run it however you want:
$ cc -O3 main.c -o matrix
$ ./matrix
How does it work?
The matrix struct makes use of two 2D arrays to encode the Matrix: the code
array for 32-bit Unicode characters and the rgb array for RGB values of the
characters (foreground color). The dimensions of these arrays depend on the
size of the terminal window. Each slot in the array corresponds to a cursor
position on the screen.
The ghosting effect, which is arguably the crowning feature of my version, is implemented by carefully scaling and mixing the RGB channels:
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;
}
The above algorithm achieves transparency by iteratively bringing the foreground color closer to the background color with each pass of the rain. This approach offers multiple advantages, such as simpler and more natural color configuration (background, foreground, and the color of the first drop) that lends itself well to Unix ricing, and of course, recreates The Matrix rain with high fidelity.
Rather than heavy-weight graphics tool kits, we use ANSI escape codes to control the terminal screen. It’s the effective use of the ANSI escape codes that greatly contributes to the minimalism of the solution:
static void term_print(const matrix *mat, size_t row, size_t col)
{
size_t idx;
idx = mat_idx(mat, row, col);
wprintf(L"\x1b[%d;%dH\x1b[38;2;%d;%d;%dm%lc",
row, col,
mat->rgb[idx].color[R],
mat->rgb[idx].color[G],
mat->rgb[idx].color[B],
mat->code[idx]);
}
Finally, the glitch effect is controlled by the following code:
if (mat.row[i] > 0 && rand() % 6 == 0) {
j = rand() % mat.row[i];
if (mat.code[mat_idx(&mat, j, mat.col[i])] != ' ') {
mat_put_code(&mat, j, mat.col[i]);
term_print(&mat, j, mat.col[i]);
}
}
The above code causes glitches in the Matrix with a probablity of 1/6.
Customizing the rain
While you can customize almost any aspect of the rain including its speed, glitch frequency, and the density of the rain, the most useful settings for ricing are the color scheme and the character set used for the rain.
There are three color settings: the head, the tail, and the background. They
are configured by setting the COLOR_*_RED, COLOR_*_GRN, and COLOR_*_BLU
definitions in main.c. The UNICODE_MIN and UNICODE_MAX values control the
Unicode block used. For instance, setting them to 0x30A1 and 0x30F6 rains
Katakana code points:

Files: source.tar.gz