This is Wireworld! Sorry, you don't know what a Wireworld is? How dare you not intimately know something I learned a few minutes ago!
A Wireworld is similar to the famous Game of Life. An infinite world of square cells, each in a distinct, finite state. But unlike boring life that has only two states: alive and dead; Wireworld has four! That's like... twice as good?
A Wireworld cell could either be: nothing, a conductor (wire), an electron tail, or an electron head. An electron head always becomes an electron tail which always becomes a wire, while a wire will stay a wire unless exactly one or two neighbors are an electron head, in which case it will follow suit (and nothing continues to be nothing).
You can see those rules in action in the animation above. You can also play with those rules over here: wireworld.klmntn.com (warning, it's only somewhat useable on mobile)
Every three months, Root sets aside three days (called "hack days") for all its engineers to work on something of their choice. This time around I wanted to have some fun and also learn a little about Svelte (Root mostly uses React & React Native). So I chose to make a browser-based Wireworld using Svelte!
- electron head
- electron tail
These four states transition by the following rules:
- null -> null
- tail -> wire
- head -> tail
- wire -> head (iff exactly 1 or 2 neighbors are an electron head)
- wire -> wire (otherwise)
Wireworlds are Turing-complete and are interesting in that they can so closely mirror digital transistor behavior with such simple rules.
This is an implementation of a Wireworld and can be found at wireworld.klmntn.com.
How did I settle on Svelte? I'm already working in React and Vue and have worked a little with Ember long ago (I've even played with the now abandoned Cell.js). Angular seems to be a different flavor of the React/Vue/Ember gang. Svelte though looks to have some novel ideas that I wanted to expose myself to.
There's really only three options for displaying anything on web:
- HTML + CSS
- SVG (+ light CSS)
The nature of a Wireworld's rendering requirements makes HTML + CSS a no-go. Canvas honestly might be the most appropriate as it can be optimized for high-frequency re-rendering. But future things I'd like to build would work well in SVG and I've already played with Canvas in the past, so I wanted to learn about graphics in SVG!
At the base of the simulation, something will need to decide what the next state should be based on the current state. This could be done in a procedural way with a switch / ifs or functional way or object-oriented. I've written about the similarities and differences before. I chose an object-oriented approach where each cell will be an object that responds to
nextState on all the cells and the world's next state has been found.
And by this I mean two things. First, SVG does not present a lot to learn above and beyond HTML + CSS (compared to the whole drawing API of a Canvas). I just put SVG tags right into Svelte components and, bang, graphics.
Second, SVG solves some of my biggest pains of drawing on Canvas. On Canvas, everything needs to be constantly erased and redrawn and if I ever want to move my viewport I'll need to do all the math to scale and translate my graphics (or learn and use another library to do it for me). With SVG, one
viewBox attribute on the top
<svg> tag handles all the scaling and translations (written by people who know a lot more about graphics than I do and offloaded to the browser so no JS needs spend time on those calculations).
Unless you have a very high paced game or some 3D graphics to render, I would recommend going down the SVG road.
I had no idea how bad listening for things like key presses and dragging events are today. Given how nice and fairly standard a lot of the APIs across browsers and platforms have become, I was shocked at how rough this space is. I think if I had to do this again, this will be one area where I defer to a library (like hammer.js).
There's plenty of examples over on the REPL site. But those examples have next to no explanation on how they work; nearly every search I tried led me to one of those examples, so it was a bit of work piecing the things together, looking at docs, and doing experiments to get things working.
Very often a misplaced wire or extra spark will cause my whole creation to devolve into closely packed electrons shooting every which way. This happens shockingly easily and I think makes a wonderful allegory to why our real computers are so hard to make and keep working correctly.
Like a real P-type transistor; our Wireworld transistor allows the signal to pass when nothing is on the gate, but blocks the signal when the gate is "on" (it even looks like a transistor diagram).
The next piece used in most designs is a signal generator:
Any loop of any shape with an electron moving around it can continuously emit electrons at a regular interval.
And go have fun! Export your creations and comment below.