Sort of! Here’s the gag…
selfportrait.exe uses pieces of its current Git commit hash to select a “paint” color and determine where to paint. Based on a heavy-handed prescription of rules (written by a human (this one in particular)), the bot draws a chunky-pixel representation of its own codebase at that moment in time while also incorporating vestiges of its previous portraits.
Each new change is committed to the repository history, producing a new commit hash. This, as you might guess, sets our bot-friend up to produce yet another portrait, ad infinitum. (Or until DigitalOcean goes out of business. Heyo.)
The rules go like this:
- The first six characters of the hash are used as the hexadecimal representation of the portrait color
- The next twenty characters of the hash string are applied to the existing portrait using a masking system we’ll see shortly
Pretty simple. Given a full commit hash
32bf2f713ca0ee423038e00cbb09a7ff8fd2dded the bot would “paint”
713ca0ee423038e00cbb using the color
“Okay, so but how does a string of 20 hexadecimal characters turn into the technicolored Rorschach blob I see on my Twitter?”
Each character is represented on the canvas with a 2-by-2 “superpixel” consisting of four “subpixels” in a binary-based pattern:
Superpixels are arranged on a 5-by-4 grid, and mirrored to increase the likelihood that we see a pattern in the chaos.
This system is enough to generate a unique representation of a given commit hash: a symmetrical smattering of pixels drawn in a specific color.
But it still leaves us with a flat representation of the bot; a single slice of its history, if you will. Can
selfportrait.exe capture its own image as a function of change over time? Can a bot paint itself as it “ages”?
I mean… Kiiiiind of.
Rather than start from scratch each iteration,
selfportrait.exe applies the new color pattern’s subpixels to the previous portrait’s subpixels using another handful of human-concocted masking rules:
- If the subpixel from the previous portrait and the new pattern are both disabled, the resulting subpixel is also disabled in the new portrait
- If the subpixel from the previous portrait is enabled and the subpixel from new pattern is disabled, the resulting subpixel is disabled in the new portrait
- If the subpixel from the previous portrait is disabled and the subpixel from new pattern is enabled, the resulting subpixel is enabled in the new portrait using the new color
- If the subpixel from the previous portrait and the new pattern are both enabled, the resulting subpixel is enabled in the new portrait using the old color
This, I hope, produces a good balance of old and new.
Admittedly, this is all very silly.
selfportrait.exe is no more capable of “painting” a “self-portrait” than a spreadsheet is able to advise you on financial matters. They only do what we tell them.
Still, I like to make Twitter bots, and the idea of making something that, with enough distance and squinting at least, gives the appearance of making something in its own image was very appealing.
I did more research while building this bot than I normally do, and you might get a kick out of reading some of what I dug into:
Maintaining colors from the previous portraits was my wife’s idea, and she only rolled her eyes a little when I retconned the schtick about it showing the bot age over time. She’s the best ❤️.
The last 14 characters —
09a7ff8fd2dded, in our example — are dumped off a pier, never to be seen again. I feel bad about not using the entire string, for some reason, like it’s cheating somehow. In the end, though, 34-character portraits were too noisy to produce anything fun.