Be fun with SVG and befunsvge
by Clément Delafargue on November 7, 2022
Finding creative ways to express yourself is not always easy when you’re all thumbs and you can’t keep the beat. Since I’m not entirely bad at programming, I gave generative art a try. I still get rubbish results, but I am having fun doing so. That’s success, as far as I am concerned.
I’ve been spamming my poor followers with ugly shapes and inscrutable code for a few days, so I tought it would be a good time to explain what I was doing.
tl;dr: I generate SVG through an esoteric stack-based language inspired by befunge. You can try it out online: https://befunsvge.cleverapps.io, but you might want read a bit more to be able to actually use it.


A link to the same program on a live playground
SVG generation for pen plotting
Pen plotters are tons of fun: instead of printing bitmaps, they move an arm with a little pen over a piece of paper. Parametric curves are a great fit for plotters, as they provide a super crisp output. Programatically generating SVG shapes is also relatively easy, so that’s an easy way to get started. Well I bought a shitty $100 plotter over ali express and never managed to get it to work, but I had fun nonetheless. I spent a fair bit of time drawing tesselated penrose triangles and I’m happy with the result, even though it’s still on a screen and not on a piece of paper.
After a bit, it became boring though, because while writing haskell is something I tremendously enjoy, it is also something I’m quite comfortable with now, so I lacked friction to guide my visual experimentations (don’t worry, Haskell is very good for abstract experimentations and provides me with ample head-scratching in this area, but that’s something different).
Befunge
Befunge is an esoteric language created in 1993. It is stack-based,
but the fun part is that the execution model is based on a 2d
grid: the source code itself. Each character in the grid is
a command, and the execution pointer moves in a direction,
executing commands in sequence. Control flow is handled by
commands changing the pointer direction. Some are unconditional,
like <^v>
(they change the pointer direction), and some are
conditional, like |
or _
(they change the pointer direction,
based on the contents of the stack). Basic arithmetic is provided
(+-*/
), comparisons with `
. The whole list of
instructions fits
on a page, so it’s relatively easy to understand and memorize it.
Writing actual programs, on the other hand, that’s a bit more
challenging.
Here are a couple examples:
A hello world
"!dlroW ,olleH">:v
|,<
@
A factorial
&>:1-:v v *_$.@
^ _$>\:^
The original befunge (befunge-93
) was later expanded into a family
of languages (funge-98
),
which generalizes befunge over the number of dimensions, and adds
new features such as concurrency).
Befunsvge
I played a bit with generative art first with Processing, then in pure JS and haskell, but sometimes the lack of constraints is a big blocker in itself. So I wondered if it would be fun to generate SVG from a purposefully constraining language, and befunge struck me as a good candidate. I don’t need a lot of abstraction to draw SVG, just math operations, and stack-based languages are fun.
So I wrote a befunge-93 implementation, enriched with a couple generative-art-oriented extensions. It’s available as a command-line tool, as well as an online playground. You can share links to the playground, program and configuration are stored in the URL.
A first example
0 >:"d"`#v_:5*0M:"d"\-5*0\Lv
1+^ >π@ >
The important part here is the loop:
0 >:"d"`#v_ v
1+^ > @ >
:"d"`
compares the counter to 100
(d
’s ascii code is
100
). _
conditionally jumps to the end of the loop when the
counter reaches 100
(_
moves to the left, then v
routes to
the line below, and @
ends the program). Before that, _
moves
to the right, to v
, then to >
then to 1+
(by wrapping around),
and then the flow goes back to the comparison bit. The jump #
command allows to jump over the v
when coming from the left. This
makes the code a bit more compact.
Then, :5*0M:"d"\-5*0\L
generates M 0 5*i L 5*(100- i) 0
, with
i
the current loop counter (remember, :
duplicates the top of the
stack, and \
swaps the first two elements). We need to do a bit of
stack magic to not forget the current i
value, and be able to compute
5*i
and (100 - i) * 5
. M
and L
pop values from the stack and
generate the corresponding SVG path commands.
SVG extensions
The goal of befunsvge is to generate files amenable to pen plotting, so it only support drawing shapes, without support for color or filling.
Since it’s easy to type greek letters with my keyboard layout, I’ve decided to use greek letters for SVG-level commands:
ρ
(rho) pops coordinates for a rectangle and outputs a<rect>
tag;ε
(epsilon) pops coordinates for an ellipse and outputs a<ellipse>
tag;π
(pi) flushes the current path and outputs a<path>
tag.
Path commands
Path is the most versatile tool in befunsvge (and possibly in
SVG). It works with a d
parameter that contains a description of the
path. It works with a curser that can move to specific (absolute or
relative) positions, and draw lines, arcs or Bézier curves between
points. Befunsvge has special support for it: a dedicated buffer
for a path description, and operators that push commands to the
buffer. Finally, π
flushes the buffer by generating a <path>
tag with the buffer contents.
M
(resp.m
) moves the cursor to an absolute (resp. relative)x,y
position without drawing anything;L
(resp.l
) draws a line to the absolute (resp. relative)x,y
position;H
(resp.h
) draws a horizontal line to the absolute (resp. relative)x
position;W
(resp.w
) draws a vertical line to the absolute (resp. relative)y
position (in SVG it’sV
andv
, butv
is already part of befunge);A
(resp.a
) draws an ellipse arc to the provided absolute (resp. relative)x,y
position, and the providedrx,ry,angle,large-arc-flag,sweep-flag
parameters;CcSsQqTt
draw various Bézier curves.
The MDN post on
d
gives you more detail about each commands. Befunsvge pops the
parameters in the same order (but from the top of the stack, so 01M
outputs M 1 0
).
Perlin noise
Generative art relies a lot on randomness, since it’s a good way to generate unique output based on a set of otherwise deterministic rules. The most common (I think) source of randomness is Perlin noise. This provides randomness with nice locality characteristics (pure random noise is not very insteresting after all). A common use is to prodecurally generate terrain.
It might be possible to implement Perlin noise in befunge-93, but
that would be a bit of a hassle, so befunsvge directly implements
it as an input function i
: it pops x,y,z
off the stack, and
pushes back the Perlin noise value for these coordinates. External
configuration allows configuring the Perlin parameters themselves
(octaves, persistence, amplification).
What’s planned next
Playing with befunsvge has been a lot of fun, but I still have a lot of ideas for further improvement.
Bitmap input
One avenue I would like to explore is reading input from an external
source, typically images, so that values for individual pixels
can be used. The input function i
was build with this in mind:
external configuration. Currently it only supports Perlin noise, but
it could be extended to other kinds of input. The issue is that it
would then be impossible to mix several input sources.
Trig functions
Befunge-93 provides support for basic arithmetic (+-*/%
), but there
is nothing available for trigonometric functions. Such functions
are fundamental when drawing circular shapes. Befunsvge support for
SVG arcs and Bézier curves allows me to cheat a little, but that is
not enough. The issue here is that these functions operate on real
numbers, not on integers, while Befunge (and Befunsvge) only provide
integers. Extending befunsvge to support floating-point numbers is a
can of worms I would very much like not opening. Another solution
would be to work on degrees and take an amplification parameter.
Step debugger
Writing simple befunsvge programs can become easy after some time, but the development experience is cleary painful. The web UI doesn’t display anything, and the command-line runner only displays the stack contents after execution has stopped. A nice addition would be a step debugger, allowing to step through program execution, inspecting the stack, and maybe adding breakpoints. I am not sure how to do it yet, and whether to have it embedded in the browser. Depending on what I want to do, I might have to rewrite the whole engine.
In conclusion
Was I able to use a pen plotter to draw nice things and put them
on my wall?
No.
But was I able to generate pieces that could be plotted and put
on a wall?
Also no.
Anyway I have fun writing abtruse programs in an obscure language, generating pictures that don’t really make sense. Sue me.