Glyph pipes
inspired by Matthew Simpson and Pipeseroni, pipes.sh1 and Microsoft, 3D Pipes2
Box-drawing pipes cross the screen as in the pipes.sh screensaver, the newest still growing behind a block cursor.
Made with Claude Opus 5.5
- Technique
- text characters
- Shape
- Any screen
- Added
- 27 September 2026
Colours
- #1C1B1Abackground
- #DAD8CEforeground
- #CF6A4Caccent
Export
FormatThis browser can’t make WebP files.
Shapecropped from 16:9
Crop
SizeThis browser can’t draw a file that large.
Notes
pipes.sh is a Bash screensaver, first posted to the Arch Linux forums in 2010, that grows pipes of box-drawing characters across a terminal. Here each pipe is a random walk that has to leave the screen again. Of forty tries per pipe, the one that best fills the emptiest part of the screen is kept, and no pipe enters the top-left corner.
Sources
Source code
wallpapers/glyph-pipes/design.py, 181 lines
"""A still frame of the pipes.sh screensaver: random walks of box-drawing glyphs cross the screen, and the newest pipe is still growing."""
import math
from collections import Counter
from itertools import pairwise
from walldye import ACCENT, ACCENT_3, BG_ALT, UI, UI_ALT, Canvas, Colour, P, Rng, design
from walldye.pixel import glyphs
type Cell = tuple[int, int]
PX, CW, CH = 2, 16, 32 # 8x16 font at px 2: one glyph cell in canvas units
BLEED = 8 # at least this much of the edge rows runs off-screen, so exiting pipes leave cleanly
DIRS: dict[str, Cell] = {"R": (1, 0), "L": (-1, 0), "D": (0, 1), "U": (0, -1)}
OPP = {"R": "L", "L": "R", "U": "D", "D": "U"}
GLYPH = {"LR": "━", "DU": "┃", "DR": "┏", "DL": "┓", "RU": "┗", "LU": "┛"}
LOOK, RUN = 8, 6 # turn look-ahead, min straight cells between turns
REGION = (20, 8) # cells per density-scoring region
QUIET = (46 / 120, 13 / 34) # the top-left corner no pipe enters, as fractions of the grid
# Oldest first, so later pipes overdraw earlier ones: (entry edge, position along it as a
# fraction of the 120x34-cell 16:9 grid, tone, most cells before it must have left).
PIPES: list[tuple[str, float, Colour, int]] = [
("D", 16 / 120, UI, 150),
("R", 29 / 34, UI, 140),
("U", 64 / 120, UI_ALT, 90),
("D", 102 / 120, BG_ALT, 110),
("L", 20 / 34, BG_ALT, 110),
("U", 112 / 120, BG_ALT, 90),
("D", 58 / 120, BG_ALT, 90),
("R", 2 / 34, BG_ALT, 120),
]
# The newest pipe, traced back from its head: cells per run, alternately right and up, before
# the last run to the right edge. The first two runs are the part still being drawn.
STAIR = {True: (8, 9, 16, 8), False: (6, 14, 10, 12)}
def step(p: Cell, k: str) -> Cell:
return p[0] + DIRS[k][0], p[1] + DIRS[k][1]
def walk(
rng: Rng,
size: Cell,
edge: str,
pos: int,
grid: dict[Cell, tuple[str, Colour]],
block: set[Cell],
quiet: Cell,
tone: Colour,
n: int,
) -> bool:
"""Add one pipe entering at `edge` to `grid`; True if it leaves the screen again within `n`
cells. It never enters `block`, the `quiet` corner or its own trail, and crosses an older
pipe only through a perpendicular straight."""
cols, rows = size
p, d = {
"R": ((cols - 1, pos), "L"),
"L": ((0, pos), "R"),
"D": ((pos, rows - 1), "U"),
"U": ((pos, 0), "D"),
}[edge]
came, run, own = edge, 0, set[Cell]()
def out(p: Cell) -> bool:
return not (0 <= p[0] < cols and 0 <= p[1] < rows)
def ok(p: Cell, k: str) -> bool:
if out(p):
return True
if p in block or p in own or (p[0] < quiet[0] and p[1] < quiet[1]):
return False
# an older pipe's perpendicular straight may be crossed, like pipes.sh overdraw
return p not in grid or grid[p][0] == ("┃" if k in "LR" else "━")
def clear(p: Cell, k: str) -> bool: # look ahead so a turn never curls back into the trail
for _ in range(LOOK):
p = step(p, k)
if out(p):
return True
if p in own or p in block:
return False
return True
if not ok(p, d):
return False
for _ in range(n):
turns = [k for k in rng.sample([k for k in DIRS if k not in (d, OPP[d])], 2) if clear(p, k)]
opts = ([d] if run < RUN or rng.random() < 0.9 else []) + (turns if run >= RUN else [])
k = next((k for k in opts if ok(step(p, k), k)), None)
if k is None:
return False
grid[p] = (GLYPH["".join(sorted(came + k))], tone)
own.add(p)
run = run + 1 if k == d else 0
came, d, p = OPP[k], k, step(p, k)
if out(p):
return True
if p in grid: # crossing: the newer pipe's straight simply overwrites the cell
grid[p] = ("━" if k in "LR" else "┃", tone)
own.add(p)
p = step(p, k)
if out(p):
return True
if not ok(p, k):
return False
run += 1
return False
@design(aspects="any")
def draw(s: Canvas) -> None:
cols, rows = math.ceil(s.w / CW), math.ceil((s.h + BLEED) / CH)
# centre the grid on the canvas, its origin on the font-pixel grid
x0, y0 = -((cols * CW - s.w) // (2 * PX)) * PX, -((rows * CH - s.h) // (2 * PX)) * PX
quiet = (round(QUIET[0] * cols), round(QUIET[1] * rows))
# The newest pipe enters from the right edge and steps down towards its head.
head = s.pick(landscape=(82 / 120, 23 / 34), portrait=(0.6, 0.62))
hc, hr = round((head.x - x0) / CW), round((head.y - y0) / CH)
a, b, c, e = STAIR[s.landscape]
way = [
(cols - 1, hr - b - e),
(hc + 1 + a + c, hr - b - e),
(hc + 1 + a + c, hr - b),
(hc + 1 + a, hr - b),
(hc + 1 + a, hr),
(hc + 1, hr),
]
accent: list[tuple[Cell, str]] = []
came = "R"
for (c0, r0), (c1, r1) in pairwise(way):
k = "L" if c1 < c0 else "R" if c1 > c0 else "D" if r1 > r0 else "U"
p = (c0, r0)
while p != (c1, r1):
if accent and accent[-1][0] == p:
accent.pop()
accent.append((p, GLYPH["".join(sorted(came + k))]))
p, came = step(p, k), OPP[k]
accent.append((way[-1], "━"))
hot = [p for p, _ in accent].index(way[-3]) # the last two runs are the hot, newest part
# a moat so the newest pipe, and its head most of all, reads on its own
block: set[Cell] = set()
for (c0, r0), _ in accent:
m = 6 if abs(c0 - hc) + abs(r0 - hr) < 6 else 2
block |= {(c0 + i, r0 + j) for i in range(-m, m + 1) for j in range(-m // 2, m // 2 + 1)}
grid: dict[Cell, tuple[str, Colour]] = {}
grow = max(1.0, (cols + rows) / 154) # a bigger grid needs longer walks to cross it
# A bigger grid gets more pipes for the same density: the first few again, entering half
# an edge further along, each right after its original.
extra = max(0, round(len(PIPES) * cols * rows / (120 * 34)) - len(PIPES))
pipes = [
q
for i, (edge, f, tone, n) in enumerate(PIPES)
for q in [(edge, f, tone, n)] + ([(edge, (f + 0.5) % 1, tone, n)] if i < extra else [])
]
for edge, f, tone, n in pipes:
pos = round(f * (cols if edge in "DU" else rows))
# of the seeded walks that cross the screen, keep the longest that fills the emptiest regions
best: tuple[float, dict[Cell, tuple[str, Colour]]] | None = None
for seed in range(40):
g = dict(grid)
if not walk(
s.rng(seed), (cols, rows), edge, pos, g, block, quiet, tone, round(n * grow)
):
continue
dens = Counter((c0 // REGION[0], r0 // REGION[1]) for c0, r0 in g)
score = len(g) - 0.02 * sum(v * v for v in dens.values())
if best is None or score > best[0]:
best = (score, g)
grid = best[1] if best else grid
for i, (p, ch) in enumerate(accent):
grid[p] = (ch, ACCENT if i >= hot else ACCENT_3)
lines = [[" "] * cols for _ in range(rows)]
for (c0, r0), (ch, _) in grid.items():
lines[r0][c0] = ch
glyphs(s, ["".join(r) for r in lines], lambda c, r, ch: grid[c, r][1], at=(x0, y0), px=PX)
# the block cursor, one cell past the pipe and 4 units clear of it
s.fill(P().rect(x0 + hc * CW - 4, y0 + hr * CH, CW, CH), ACCENT)"""A still frame of the pipes.sh screensaver: random walks of box-drawing glyphs cross the screen, and the newest pipe is still growing."""
import math
from collections import Counter
from itertools import pairwise
from walldye import ACCENT, ACCENT_3, BG_ALT, UI, UI_ALT, Canvas, Colour, P, Rng, design
from walldye.pixel import glyphs
type Cell = tuple[int, int]
PX, CW, CH = 2, 16, 32 # 8x16 font at px 2: one glyph cell in canvas units
BLEED = 8 # at least this much of the edge rows runs off-screen, so exiting pipes leave cleanly
DIRS: dict[str, Cell] = {"R": (1, 0), "L": (-1, 0), "D": (0, 1), "U": (0, -1)}
OPP = {"R": "L", "L": "R", "U": "D", "D": "U"}
GLYPH = {"LR": "━", "DU": "┃", "DR": "┏", "DL": "┓", "RU": "┗", "LU": "┛"}
LOOK, RUN = 8, 6 # turn look-ahead, min straight cells between turns
REGION = (20, 8) # cells per density-scoring region
QUIET = (46 / 120, 13 / 34) # the top-left corner no pipe enters, as fractions of the grid
# Oldest first, so later pipes overdraw earlier ones: (entry edge, position along it as a
# fraction of the 120x34-cell 16:9 grid, tone, most cells before it must have left).
PIPES: list[tuple[str, float, Colour, int]] = [
("D", 16 / 120, UI, 150),
("R", 29 / 34, UI, 140),
("U", 64 / 120, UI_ALT, 90),
("D", 102 / 120, BG_ALT, 110),
("L", 20 / 34, BG_ALT, 110),
("U", 112 / 120, BG_ALT, 90),
("D", 58 / 120, BG_ALT, 90),
("R", 2 / 34, BG_ALT, 120),
]
# The newest pipe, traced back from its head: cells per run, alternately right and up, before
# the last run to the right edge. The first two runs are the part still being drawn.
STAIR = {True: (8, 9, 16, 8), False: (6, 14, 10, 12)}
def step(p: Cell, k: str) -> Cell:
return p[0] + DIRS[k][0], p[1] + DIRS[k][1]
def walk(
rng: Rng,
size: Cell,
edge: str,
pos: int,
grid: dict[Cell, tuple[str, Colour]],
block: set[Cell],
quiet: Cell,
tone: Colour,
n: int,
) -> bool:
"""Add one pipe entering at `edge` to `grid`; True if it leaves the screen again within `n`
cells. It never enters `block`, the `quiet` corner or its own trail, and crosses an older
pipe only through a perpendicular straight."""
cols, rows = size
p, d = {
"R": ((cols - 1, pos), "L"),
"L": ((0, pos), "R"),
"D": ((pos, rows - 1), "U"),
"U": ((pos, 0), "D"),
}[edge]
came, run, own = edge, 0, set[Cell]()
def out(p: Cell) -> bool:
return not (0 <= p[0] < cols and 0 <= p[1] < rows)
def ok(p: Cell, k: str) -> bool:
if out(p):
return True
if p in block or p in own or (p[0] < quiet[0] and p[1] < quiet[1]):
return False
# an older pipe's perpendicular straight may be crossed, like pipes.sh overdraw
return p not in grid or grid[p][0] == ("┃" if k in "LR" else "━")
def clear(p: Cell, k: str) -> bool: # look ahead so a turn never curls back into the trail
for _ in range(LOOK):
p = step(p, k)
if out(p):
return True
if p in own or p in block:
return False
return True
if not ok(p, d):
return False
for _ in range(n):
turns = [k for k in rng.sample([k for k in DIRS if k not in (d, OPP[d])], 2) if clear(p, k)]
opts = ([d] if run < RUN or rng.random() < 0.9 else []) + (turns if run >= RUN else [])
k = next((k for k in opts if ok(step(p, k), k)), None)
if k is None:
return False
grid[p] = (GLYPH["".join(sorted(came + k))], tone)
own.add(p)
run = run + 1 if k == d else 0
came, d, p = OPP[k], k, step(p, k)
if out(p):
return True
if p in grid: # crossing: the newer pipe's straight simply overwrites the cell
grid[p] = ("━" if k in "LR" else "┃", tone)
own.add(p)
p = step(p, k)
if out(p):
return True
if not ok(p, k):
return False
run += 1
return False
@design(aspects="any")
def draw(s: Canvas) -> None:
cols, rows = math.ceil(s.w / CW), math.ceil((s.h + BLEED) / CH)
# centre the grid on the canvas, its origin on the font-pixel grid
x0, y0 = -((cols * CW - s.w) // (2 * PX)) * PX, -((rows * CH - s.h) // (2 * PX)) * PX
quiet = (round(QUIET[0] * cols), round(QUIET[1] * rows))
# The newest pipe enters from the right edge and steps down towards its head.
head = s.pick(landscape=(82 / 120, 23 / 34), portrait=(0.6, 0.62))
hc, hr = round((head.x - x0) / CW), round((head.y - y0) / CH)
a, b, c, e = STAIR[s.landscape]
way = [
(cols - 1, hr - b - e),
(hc + 1 + a + c, hr - b - e),
(hc + 1 + a + c, hr - b),
(hc + 1 + a, hr - b),
(hc + 1 + a, hr),
(hc + 1, hr),
]
accent: list[tuple[Cell, str]] = []
came = "R"
for (c0, r0), (c1, r1) in pairwise(way):
k = "L" if c1 < c0 else "R" if c1 > c0 else "D" if r1 > r0 else "U"
p = (c0, r0)
while p != (c1, r1):
if accent and accent[-1][0] == p:
accent.pop()
accent.append((p, GLYPH["".join(sorted(came + k))]))
p, came = step(p, k), OPP[k]
accent.append((way[-1], "━"))
hot = [p for p, _ in accent].index(way[-3]) # the last two runs are the hot, newest part
# a moat so the newest pipe, and its head most of all, reads on its own
block: set[Cell] = set()
for (c0, r0), _ in accent:
m = 6 if abs(c0 - hc) + abs(r0 - hr) < 6 else 2
block |= {(c0 + i, r0 + j) for i in range(-m, m + 1) for j in range(-m // 2, m // 2 + 1)}
grid: dict[Cell, tuple[str, Colour]] = {}
grow = max(1.0, (cols + rows) / 154) # a bigger grid needs longer walks to cross it
# A bigger grid gets more pipes for the same density: the first few again, entering half
# an edge further along, each right after its original.
extra = max(0, round(len(PIPES) * cols * rows / (120 * 34)) - len(PIPES))
pipes = [
q
for i, (edge, f, tone, n) in enumerate(PIPES)
for q in [(edge, f, tone, n)] + ([(edge, (f + 0.5) % 1, tone, n)] if i < extra else [])
]
for edge, f, tone, n in pipes:
pos = round(f * (cols if edge in "DU" else rows))
# of the seeded walks that cross the screen, keep the longest that fills the emptiest regions
best: tuple[float, dict[Cell, tuple[str, Colour]]] | None = None
for seed in range(40):
g = dict(grid)
if not walk(
s.rng(seed), (cols, rows), edge, pos, g, block, quiet, tone, round(n * grow)
):
continue
dens = Counter((c0 // REGION[0], r0 // REGION[1]) for c0, r0 in g)
score = len(g) - 0.02 * sum(v * v for v in dens.values())
if best is None or score > best[0]:
best = (score, g)
grid = best[1] if best else grid
for i, (p, ch) in enumerate(accent):
grid[p] = (ch, ACCENT if i >= hot else ACCENT_3)
lines = [[" "] * cols for _ in range(rows)]
for (c0, r0), (ch, _) in grid.items():
lines[r0][c0] = ch
glyphs(s, ["".join(r) for r in lines], lambda c, r, ch: grid[c, r][1], at=(x0, y0), px=PX)
# the block cursor, one cell past the pipe and 4 units clear of it
s.fill(P().rect(x0 + hc * CW - 4, y0 + hr * CH, CW, CH), ACCENT)
Run it yourself
$ git clone https://github.com/nickolaj-jepsen/walldye && cd walldye$ uv run walldye render glyph-pipes --theme fireproof -o glyph-pipes-fireproof-16x9.svg