> Most importantly, there is no permacomputing kit to buy. See permacomputing as invitation to collectively and radically rethink computational culture. It is not a tech solution searching for a problem.
2026
slime molds / electroluminescent screens / imaginary computing
My goal for this jam is to combine three of the suggested themes: slime molds, electroluminescent screens, and imaginary computing. The idea is to design a hh:mm watch face (maybe in the style of a 7-segment display) in which the numerals are lit up by the dynamics of slime mold growth. As the minutes change, we might discontinuously change the external forcing (aka external stimuli/food source) to get the mold to reconfigure itself into the shape of the next timestamp. I have no idea if this will work (that is: if there are parameters we can choose in a slime mold simulation that will actually yield somewhat recognizable watch-face-digits), but either way I'll learn a bit about lua, l5/processing, and slime molds.
We'll be following Jeff Jones' paper (there's a beautiful demonstration and exposition here).
Journal follows.
september 25
Decided to participate in the evening of the first day. I had incidentally started experimenting with Processing just earlier this week, so I figured it'd be a good continuation of that. The slime mold theme reminded me of Merlin Sheldrake's book on fungi, Entangled Life, which I read a few months ago (and remembered enough from to know that slime molds are not fungi!). I think that's where I first read about the maze-solving and path-optimizing capabilities of slime molds, as well as new unconventional approaches to computing through fungi.
Here's a gif of what the simulation looks like so far:
One problem I ran into is that rendering each particle individually via calls
to L5's point(x, y) seemed pretty slow, which makes sense. For now
I'm bypassing L5 a bit by using Love2d's
ImageData
as a buffer, and doing the rendering (via Image:replacePixels) in
one pass, which seems to be faster.
The simulation algorithm is described nicely in both the original paper and in Sage Jenson's schematic diagram here, so I won't go into details (I'll have the code up somewhere at some point). The implementation was actually surprisingly straightforward; I didn't have to do much debugging at all. To be clear: I have no idea if I've implemented Jones' algorithm correctly. The results look reasonable, though, so that's good enough for now. There were a few minor annoyances coming from being new to Lua, though:
- there's some negotiation needed when dealing with the coordinate systems (which use zero-indexing), as Lua is one-indexed
-
Lua doesn't have a
continuestatement, so I wrote the particle sensing decisions as a slightly awkward (in my view, at least) if-spaghetti -
the fact that variables in Lua by default are global (scoped variables are
declared via the
localkeyword) has tripped me up a few times
> listening to: Amusing Ourselves To Death - See How
september 26
Didn't have much time today, but managed to change the coordinate system over to
periodic boundary conditions (effectively a torus). The nice thing about
wrapping around like this is that you can delete all the is_in_bounds
checks and instead just work directly with expressions like x % width.
The modulus operator works as you would want it to with negative numbers, which is
convenient... though Lua's one-indexing kinda gets in the way here again by making
us have to conjugate by a shift-by-one operation beforehand.
The behavior of the slime mold under periodic boundary conditions
changes to roughly what you would expect: there are no corner/edge artifacts, and
the dynamics are continuous across boundaries.
Currently I seem to be getting around 15fps when working with around 5000 particles on my m1 macbook air. Jones in his paper studies I probably can't expect crazy performance trying to run a particle simulation on the cpu, but I'd love to optimize this at least a bit.
I think the diffusion/decay step of the simulation is probably pretty heavy.
Currently this consists of looping through every pixel of and diffusing the trail
of stimulant left by the mold (the external stimuli are not modified) by taking an
average of the values in the 3x3-square of tiles centered at the selected tile.
Every step of the simulation, then, the diffusion consists of roughly
9n^2 additions and n^2 divisions.
I did a quick search to see if there's any cleverer approaches to this mean-filtering. I found this paper, which thankfully seems pretty elementary. The idea is to reduce the number of additions and divisions whereever possible. I've never really done much performance-critical coding, so it feels kinda funny to me, but I'll probably try it out tomorrow.
Oh, I also started this devlog website. I was inspired by the theme of electroluminescence and wanted to experiment with that old amber phosphor aesthetic... sorry if it's a little too much. I took some color ideas from this vs code theme.
> listening to: MINIMIS - SSDD
september 27
Finished writing logs for the previous days and got this website up on squeak. Now for the hard part... working on optimizing the diffusion algorithm.
After spending an embarrassing amount of time rewriting the diffusion algorithm to be slightly less naive, I'm able to stay at a solid 30fps up to ~8000 particles. For the 200x200 window I'm working with here, this is probably overkill -- Jones suggests experimenting with particle number between 3% and 15% of the total number of pixels, which comes out to between 1200 and 6000 particles in our case.
One interesting thing to note is that -- with the parameters we've chosen here -- the mold tends to form semi-stable 4-, 5-, or 6-gons. The video below is a typical example (with no external stimuli):
The optimization of the diffusion code is pretty straightforward. Instead of recomputing the sum of all the neighbors of a given pixel (including itself) in order to compute the mean, we pre-compute and store, at the start of every new row, the sum of the length-3 columns along that row. This cuts down the number of redundant additions significantly.
I got the idea from this paper I mentioned above.
In retrospect, the optimization is obvious, but I wouldn't have thought this would make such
a noticeable difference. I implemented a few of the optimizations mentioned there, including
the one which avoids divisions entirely. The zero-division optimization should be the fastest,
according to their results, but I didn't see much of an improvement over the version I
implemented (add_red2):
mean(s) stdev(s)
baseline: 0.043 0.001
add_red1: 0.025 0
add_red2: 0.015 0
zero_div: 0.015 0
I've also added a bit of functionality to add blobs of external stimuli via mouse (they are visible in white, but pressing a key toggles display of external stimuli) to help me get a sense of how they might affect the overall shape of the mold. The goal would be to use external stimuli to shape the mold into visibly digit-like forms comprising a digital watch face. After playing with this for a while, though, I'm not so sure if this is possible without setting specific dead-zones...
> listening to: Find - Synaptyx
september 28
Busy, only wrote two little bits of code today:
- set up little rectangles in an auxillary L5 program to figure out what size I want the watch digits to be -- landed on roughly 40px-by-70px with 10px of padding (note that the sensing distance is a Euclidean 9px)
- set up the ability to specify "dead zones" where slime mold cannot grow/move to
I think the two of these, together with food (aka external stimuli sources) might allow for drawing little wobbly slimy digits. I don't think the solution will be pretty or elegant, unfortunately, but now that I actually have some visual intuition about the dynamics, I'm not sure I can expect the particles to form nice digits just using external stimuli. Anyway, I'll update with details and pictures tomorrow, it's getting late.
september 29
Busy, exhausted, no code today. Worried my original goal may have been too ambitious.
> listening to: Callisto - Sl8r
september 30
Instead of establishing dead zones (pixels into which movement is disallowed), we can achieve something similar by using negative external stimuli values. It's not quite the same, as we still see filaments extending through the perimeter depending on the initial conditions. Maybe we can experiment with setting up pre-arranged stimuli (both positive and negative) for each digit, and discontinuously iterate through them as the clock ticks.
I've manually implemented different little rectangles of negative stimuli for each digit 0-9. Et voila, two screenshots two minutes apart:
It's ugly as hell for now, but maybe I'll have time before the end of the jam to clean it up. It qualifies as a working proof of concept, I think. I don't think I want to do too much more, but here's a tentative to-do list for myself:
- show/hide stimuli via mouse-clicks
- two modes: fullscreen non-clock sim (very pretty, very cool, not my idea) and the clock (ugly, kinda static, my idea)
- play with keeping stimuli at 0 for a few seconds before transitioning to the new time
> listening to: data.matrix - Ryoji Ikeda
october 1
Added a mode-selector to switch between the full simulator and the clock. I haven't bothered tweaking things to make the clock look better... maybe when I find the energy later.
I think it's time to submit! This is my first ever submission to a jam of any variety so I'm feeling pretty proud!
> listening to: Live at Sydney Opera House - Underworld
about
A week-long jam around the new creative coding library L5.
> L5 (https://l5lua.org/) is a new creative coding library for making art with code. It is based on Processing (and p5.js) and implemented in Lua. L5 is designed to be lightweight and to run on older computers and low-powered machines. It is a response to principles of permacomputing, which includes resisting planned obsolescence and wasteful practices of Big Tech.