Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

art.generative

L-systems, fractals, the Mandelbrot set, cellular automata, mazes, starfields

Example results generated on 2026-10-08. Ones using now, today or randomness will differ when you run them: press Run on any example to run it in your browser, after editing it if you like.

Functions

functiondescription
lsystem(axiom: str, rules: map, angle: num, n: int, width?: int)rewrite axiom n times with rules (one character → its replacement), then draw it with a turtle in braille, width characters wide (default 60). F and G draw a step, f steps without drawing, + and - turn by angle degrees, | turns around, [ and ] save and restore position; other characters do nothing. Starts facing up
fractal(name?: str, n?: int, width?: int)a named L-system fractal: “dragon”, “koch”, “hilbert”, “sierpinski”, “levy”, “gosper”, “tree”, “fern” or “bush”; n is the depth, width as in lsystem. No name lists them
rule(n: int, width?: int, steps?: int)an elementary cellular automaton, 0-255, grown from one cell for steps rows (default width / 2) on a wrapping row of width cells (default 64); two rows per line
spiral(size?: int)an Ulam spiral: 1, 2, 3… wound out from the center with the primes as dots, which line up on diagonals; size characters wide (default 40)
starfield(width: int, height: int, seed?: int)a random night sky; the same seed gives the same sky
mandelbrot(width?: int, height?: int)the Mandelbrot set in ASCII, default 72×24
life(start: str, steps?: int)run Conway’s Game of Life for steps (default 1) and draw the live cells; start is rows of # and . or one of “glider”, “blinker”, “pulsar”, “r_pentomino”
maze(width?: int, height?: int)a random perfect maze (one path between any two cells), default 20×10 cells

lsystem

lsystem(axiom: str, rules: map, angle: num, n: int, width?: int): rewrite axiom n times with rules (one character → its replacement), then draw it with a turtle in braille, width characters wide (default 60). F and G draw a step, f steps without drawing, + and - turn by angle degrees, | turns around, [ and ] save and restore position; other characters do nothing. Starts facing up

lsystem("F", {F: "F+F-F-F+F"}, 90, 3, 30)
# →              ⡤⠇
# →            ⣀⡏⣏⡇
# →         ⢀⣀⣖⡃
# →       ⢀⣰⠚ ⠓⣗⣆⣖⡆
# →      ⢰⢺⢲   ⡖⡗⡗⡆
# →    ⢠⠼⠉⠈⠉   ⠉⠁⠉⠁
# →  ⡤⠏⠹⠽
# → ⣏⡁
# →  ⠓⣆⣰⣲
# →    ⠘⢲⣀⢀⣀   ⣀⡀⣀⡀
# →      ⠸⢼⠼   ⠧⡧⡧⠇
# →       ⠈⠹⢤ ⡤⡯⠏⠯⠇
# →         ⠈⠉⠯⡅
# →            ⠉⣇⣏⡇
# →              ⠓⡆

See also: fractal

fractal

fractal(name?: str, n?: int, width?: int): a named L-system fractal: “dragon”, “koch”, “hilbert”, “sierpinski”, “levy”, “gosper”, “tree”, “fern” or “bush”; n is the depth, width as in lsystem. No name lists them

fractal("koch", 3, 30)
# →           ⡀⠠⡴⢧⠄⢀
# →         ⠐⡞⠑⠚  ⠓⠊⢓⡆
# →    ⣀⣠⣀  ⢈⣙⠄    ⠠⣋⡁  ⣀⣠⣀
# → ⣀⡴⣀⡕ ⢪⣀⢦⣀⠇      ⠐⣅⡴⣀⡕ ⢪⣀⢦⣀
# → ⠯⡄                      ⢠⠽
# → ⢖⠋                      ⠙⡲
# → ⠓⠲⠒⡢                  ⢔⠒⠖⠚
# →    ⣉⡧                ⠰⣉
# → ⡤⠴⠤⠕                  ⠪⠤⠦⢤
# → ⠮⣄                      ⣠⠵
# → ⣖⠃                      ⠘⣲
# → ⠉⠳⠉⡣ ⢜⠉⠞⠉⡆      ⠠⡋⠳⠉⡣ ⢜⠉⠞⠉
# →    ⠉⠙⠉  ⢈⣩⠂    ⠐⣍⡁  ⠉⠙⠉
# →         ⠠⢧⡠⢤  ⡤⢄⡬⠇
# →           ⠁⠐⠳⡞⠂⠈
fractal()
# → ["dragon", "koch", "hilbert", "sierpinski", "levy", "gosper", "tree", "fern", "bush"]

See also: lsystem, rule

rule

rule(n: int, width?: int, steps?: int): an elementary cellular automaton, 0-255, grown from one cell for steps rows (default width / 2) on a wrapping row of width cells (default 64); two rows per line

rule(30, 32)
# →                ▄█▄
# →              ▄█▀▄▄█▄
# →            ▄█▀▄▄█▄ ▄█▄
# →          ▄█▀▄▄█▄  ▄█▄▄█▄
# →        ▄█▀▄▄█▄ ▄█▀▀▄   ▄█▄
# →      ▄█▀▄▄█▄  ▄█ █▀▀▀ █▀▄▄█▄
# →    ▄█▀▄▄█▄ ▄█▀▀▄▄█▀▄▄█▀ █▄ ▄█▄
# →  ▄█▀▄▄█▄  ▄█ █▀▀▄ ▄█▄▄█▀▀▄▄█▄▄█▄
rule(90, 32, 16)
# →                ▄▀▄
# →              ▄▀▄ ▄▀▄
# →            ▄▀▄     ▄▀▄
# →          ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄
# →        ▄▀▄             ▄▀▄
# →      ▄▀▄ ▄▀▄         ▄▀▄ ▄▀▄
# →    ▄▀▄     ▄▀▄     ▄▀▄     ▄▀▄
# →  ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄

See also: life, fractal

spiral

spiral(size?: int): an Ulam spiral: 1, 2, 3… wound out from the center with the primes as dots, which line up on diagonals; size characters wide (default 40)

spiral(20)
# → ⢀⠄⠁⢐⢄⠄⠐ ⠔⠑⠄⠕   ⢁ ⠁⢐
# → ⢀⠄ ⢀⠁⢁  ⠁⠔⠁⢔⢐ ⠐⢄⠁⠄⠄⠁
# → ⠐⠑⢄⠁⢁⠄ ⠕⠁⢀ ⢅⢀⠐⢅⢐⢀ ⠐⠐
# → ⢀⠁⢁⠐⢀ ⢑⢀⠐⢑⠄⠄ ⢀⠅⢁⢄⠑⠄⠄
# →  ⠐⠄⠄⠄⠔⠄⠔⠔⢄⢁⢕⠐⠑ ⠄⠐⢐⠐
# →   ⢀⠐⢀⢀ ⢑⢔⠑⢌⠁⢁⢁⠁⢀⠁⢁⢁
# → ⢀⢅  ⢁ ⢅⠄⠑ ⠄⠁⢄ ⠕⠁⢀⠁⠄⢄
# →   ⠅⢄⠄⢅ ⠐⠑ ⠕⢅⢀⠐⠄⠐ ⠄⠔
# →  ⠑⠐⠁⠁⢀⠐⢅⠄ ⢅⠔⠁⢁ ⠐⠄ ⢐⢅
# → ⢐ ⢐⢀⠁⢁⠐ ⢁   ⠐ ⢐⠄ ⠑⠄

See also: is_prime

starfield

starfield(width: int, height: int, seed?: int): a random night sky; the same seed gives the same sky

starfield(30, 4, 7)
# →            .
# →     ·            ·
# →             · ·   + +
# →              . ·

See also: negative

mandelbrot

mandelbrot(width?: int, height?: int): the Mandelbrot set in ASCII, default 72×24

mandelbrot(40, 12)
# → 
# →                           ...:
# →                        ...:@@@..
# →                     ..#+=@@@@@@@:#:.
# →             .........#@@@@@@@@@@@@-.
# →            ..:@@@@@:@@@@@@@@@@@@@@@-
# →    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-..
# →            ..:@@@@@:@@@@@@@@@@@@@@@-
# →             .........#@@@@@@@@@@@@-.
# →                     ..#+=@@@@@@@:#:.
# →                        ...:@@@..
# →                           ...:

See also: life

life

life(start: str, steps?: int): run Conway’s Game of Life for steps (default 1) and draw the live cells; start is rows of # and . or one of “glider”, “blinker”, “pulsar”, “r_pentomino”

life("blinker")
# → #
# → #
# → #
life("glider", 4)
# → .#.
# → ..#
# → ###

See also: maze

maze

maze(width?: int, height?: int): a random perfect maze (one path between any two cells), default 20×10 cells

maze(6, 3)
# → ██  ██████████████████████
# → ██  ██          ██      ██
# → ██  ██  ██████  ██  ██  ██
# → ██      ██      ██  ██  ██
# → ██████████  ██████  ██  ██
# → ██                  ██  ██
# → ██████████████████████  ██

See also: life

More examples

grow things

# a dragon curve
fractal("dragon", 8, 30)
# →                    ⣀⣸⣉⡇ ⢀⣸⣉⡇
# →                    ⠓⢺⠒⡆⡖⢺⢺⠒⡆⡖⠂
# →   ⠸⠭⡧⠏⠹⢤       ⢠⢤  ⠯⢽⠭⡯⡅⠈⠉ ⠉⠯⠅
# → ⣖⣲⣰⣒⡃ ⠐⠚      ⣖⣺⣚ ⣀⣖⣚ ⠓⠃   ⣆⡖⠂
# →  ⠸⢼⠤⠇         ⡤⢼⢼⠤⡧⡧⢼⠤⡄
# → ⣀⣀⢘⣒⣆⣖⣲  ⣀⣰⣲  ⣓⣺⣺⣒⣗⣗⣺⠒⣗⡆
# → ⠧⢼⢼⠤⡧⡧⢤⢠⠤⡧⢼⢤ ⡤⡧⢼⢼⠤⡧⡧⢤
# →  ⠈⠉ ⠉⠁⠈⢹⣉⣏⣹⣹⣉⡁⠉⠉⠈⠉⣏⣏⣹⣉⣇⡀
# →      ⡖⢲⢰⠒⡗⠚⠘⠒⠃ ⢰⢲ ⡖⡗⠚ ⠓⠃
# →      ⠉⠹⠽⠉⠯⠽    ⠈⠹⠭⠏⠯⠽
# a tree in a box
fractal("tree", 6, 24).boxed("round")
# → ╭───────────────────╮
# → │  ⢀⡀⠐⢾ ⡯⠂ ⠐⠪⡇⡹⠒ ⣀  │
# → │ ⣀⠓⣇  ⢹     ⢹⠁ ⢀⠗⢃ │
# → │ ⠞⠉⠉⠑⠤⣸     ⢸⡠⠔⠉⠉⠱ │
# → │      ⠘⢆   ⢀⠎      │
# → │       ⠈⢢ ⣠⠃       │
# → │         ⢳⠃        │
# → │         ⢸         │
# → │         ⢸         │
# → │         ⢸         │
# → │         ⢸         │
# → │         ⢸         │
# → │         ⢸         │
# → ╰───────────────────╯
# Sierpinski, two ways
rule(90, 32, 16).beside(fractal("sierpinski", 4, 16), 4)
# →                ▄▀▄                         ⣰⣇
# →              ▄▀▄ ▄▀▄                      ⣼⣷⣾⣧
# →            ▄▀▄     ▄▀▄                  ⢀⡾⢿⡄⢠⡿⢷⡀
# →          ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄               ⢠⣞⠛⠚⠛⠛⠓⠛⣳⡄
# →        ▄▀▄             ▄▀▄            ⣠⣿⣻⣦    ⣴⣟⣿⣄
# →      ▄▀▄ ▄▀▄         ▄▀▄ ▄▀▄         ⣰⣯⡉⠉⣹⣧⡀⢀⣼⣏⠉⢉⣽⣆
# →    ▄▀▄     ▄▀▄     ▄▀▄     ▄▀▄      ⠼⠷⠼⠷⠼⠷⠼⠷⠾⠧⠾⠧⠾⠧⠾⠧
# →  ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄ ▄▀▄
# invent a plant
lsystem("X", {X: "F[-X][X]F[-X]+FX", F: "FF"}, 25, 4, 30)
# → ⣀⡀⠐⣄⡀ ⠈⢧ ⡄
# →  ⠈⠉⠙⠳⡀ ⠈⢷⡇    ⠒⡄⢀
# →      ⠈⠲⣄⢻⢆⣜    ⠸⣸
# →         ⠹⣿⠎     ⡟  ⢰
# →         ⡀⠹⣀   ⠢⡌⣇ ⢠⣏⡄
# →         ⠉⠓⢵⣇  ⠠⡸⣿⣜⠟⡉
# →            ⢻   ⣷⣿⡿⠊⢱
# →            ⠈⢣ ⣬⡿⡇ ⢠⣏⡀
# →              ⢣⡇⣧⣏⣼⡟⠋
# →              ⢸⡝⢺⣵⣿⠖⠁
# →              ⢸⢠⠋
# →              ⢸⠃
# →              ⢸
# →              ⢸
# →              ⢸
# the Mandelbrot set
mandelbrot()
# → 
# →                                                .-.
# →                                                .......
# →                                               ...-=:...
# →                                           .....:@@@@@:..
# →                                       .........:@@@@+:.........
# →                                    ....:@@:%@@@@@@@@@@@@@:.:::#.
# →                                 .....*.#@@@@@@@@@@@@@@@@@@@@@:..
# →                      ................-@@@@@@@@@@@@@@@@@@@@@@@=...
# →                     ....:@-.:@::...:=@@@@@@@@@@@@@@@@@@@@@@@@@-..
# →                    ...:.-@@@@@@@@=:-@@@@@@@@@@@@@@@@@@@@@@@@@@@-.
# →             ........#=:+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.
# →      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+:...
# →             ........#=:+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.
# →                    ...:.-@@@@@@@@=:-@@@@@@@@@@@@@@@@@@@@@@@@@@@-.
# →                     ....:@-.:@::...:=@@@@@@@@@@@@@@@@@@@@@@@@@-..
# →                      ................-@@@@@@@@@@@@@@@@@@@@@@@=...
# →                                 .....*.#@@@@@@@@@@@@@@@@@@@@@:..
# →                                    ....:@@:%@@@@@@@@@@@@@:.:::#.
# →                                       .........:@@@@+:.........
# →                                           .....:@@@@@:..
# →                                               ...-=:...
# →                                                .......
# →                                                .-.
# a glider, 8 steps on
life("glider", 8)
# → .#.
# → ..#
# → ###
# draw your own
life(".#.\n.#.\n.#.", 1)
# → "###"
# a maze
maze(12, 6)
# → ██  ██████████████████████████████████████████████
# → ██          ██                      ██          ██
# → ██████████  ██████  ██████████████  ██  ██████  ██
# → ██      ██      ██      ██      ██  ██      ██  ██
# → ██  ██  ██████  ██  ██  ██████  ██  ██████  ██  ██
# → ██  ██      ██  ██  ██  ██      ██      ██  ██  ██
# → ██  ██  ██████  ██████  ██  ██  ██████  ██████  ██
# → ██  ██      ██      ██  ██  ██      ██          ██
# → ██  ██████  ██████  ██  ██  ██████████████████  ██
# → ██  ██  ██      ██      ██      ██          ██  ██
# → ██  ██  ██████  ██████████  ██  ██  ██  ██████  ██
# → ██          ██              ██      ██          ██
# → ██████████████████████████████████████████████  ██