art_blocks · CherniakRingers
Cherniak Ringers (Dmitri Cherniak — Ringers)
An implementation of Dmitri Cherniak's *Ringers* algorithm (Art Blocks Curated, January 2021, 1,000 NFTs) — one of the most-cited generative-art projects of the NFT era, and the source of *Ringers #879* ('The Goose') and *Ringers #962* (acquired by LACMA). Cherniak's algorithm: lay out N pegs, sort them by angle from the (centroid or offset) anchor, draw a closed loop visiting each peg in sorted order, then repeat thousands of times with a per-wrap anchor drift so the loops cross through the canvas in different orders. Cherniak: 'essentially it looks for the centroid for the balanced ringer. It looks for the centroid. So it kind of averages all the pegs and then it tries to loop a string around each of the pegs based on kind of it sorts all the pegs from the angle it forms with the centroid.' Each segment is offset tangentially on each peg end (a per-wrap, per-segment sine) so successive wraps pass tangent on different sides of each peg — the source of the dense string-intersection look.
Original: https://www.artblocks.io/collection/ringers-by-dmitri-cherniak
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
For each wrap w in [0, num_wraps): pick anchor a_w = centroid_or_offset + drift(w); compute angles[i] = atan2(peg[i].y - a_w.y, peg[i].x - a_w.x); sort pegs by angle; for each adjacent pair (peg[order[k]], peg[order[k+1]]) draw a line whose endpoints are offset by tangent_drift * peg_radius perpendicular to the segment. With num_wraps = 512 and 22 pegs, the canvas is crossed by 22 * 512 = 11,264 segments with thousands of intersection points.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 600 | 200–1500 | Square canvas side length (px). |
num_pegs | int | 16 | 3–60 | Number of pegs N (Cherniak: 9–24, peak density at 20–24). |
layout | str | circle | null–null | circle|grid|random — peg placement. |
peg_size_min | float | 6 | 1–60 | Minimum peg radius in px. |
peg_size_max | float | 14 | 2–100 | Maximum peg radius in px. |
string_color | tuple | 40,60,130 | null–null | RGB string colour. |
background_color | tuple | 15,15,18 | null–null | RGB background colour (Cherniak: black / dark-mode). |
num_wraps | int | 512 | 1–4096 | Number of closed-loop wraps (each contributes N segments). |
anchor | str | centroid | null–null | centroid|offset — anchor for the sort (Cherniak's 'arbitrary point' bug). |
wrap_orientation | str | cw | null–null | cw|ccw — direction of winding. |
bullseye_prob | float | 0 | 0–1 | Probability that a peg is rendered as concentric-ring bullseye. |
fill_color_mode | str | string | null–null | single|palette|string — peg colour mode. |
seed | int | 7 | 0–2147483647 | RNG seed for reproducibility. |
Reference
First 60 lines of reference.py. Full source:
library_external/art_blocks/CherniakRingers/reference.py
"""CherniakRingers — Dmitri Cherniak's "Ringers" string-on-pegs algorithm.
Inspired by Dmitri Cherniak's *Ringers* (Art Blocks Curated, January
2021) — 1,000 generative artworks that "explore all the ways a string
can wrap around a set of pegs." It is one of the defining generative-
art projects of the NFT era and produced the iconic *Ringers #879*
("The Goose"), one of the most recognisable generative artworks ever
made. Ringers was acquired by LACMA (*Ringers #962*) and Sotheby's
auctioned *#879* for $6.2 million in 2023.
Cherniak describes the algorithm in his own words (Bankless interview,
2021):
"There are an almost infinite number of ways to wrap a string
around a set of pegs. ... Each output from 'Ringers' is derived
from a unique transaction hash and generated in Javascript in
the browser. Feature variations include peg count, sizing, layout,
wrap orientation, and a few colourful flourishes for good measure."
In a later After-Dinner-Mints podcast (May 2021) he gave the
algorithmic kernel:
"Essentially it looks for the centroid for the balanced ringer.
It looks for the centroid. So it kind of averages all the pegs
and then it tries to loop a string around each of the pegs based
on kind of it sorts all the pegs from the angle it forms with the
centroid."
The algorithm we implement:
1. Lay out N pegs on the canvas. Three layouts are typical of
Ringers: a circle (the canonical 'balanced' layout), a 3x3 grid
(the famous "3x3 grid" trait), and a random constellation.
2. Pick an "anchor" point — the centroid of the pegs, or an
arbitrary off-centre point (Cherniak's "arbitrary point" bug
that he kept because it made for interesting looks).
3. Sort the pegs by angle from the anchor.
4. Draw the string as a closed loop: from peg i, draw a straight
line to peg i+1, and so on around the sorted order. Each line
either stays in front of (covering) or behind (occluded by) the
peg, depending on the wrap orientation.
5. After K wraps (default 512), the canvas is densely threaded
with string intersections — the canonical Ringers look.
6. Each peg is filled with its assigned colour (the rare
"bullseye" trait gives a concentric ring instead).
Reference:
- https://www.artblocks.io/collection/ringers-by-dmitri-cherniak
- https://www.curated.xyz/editorial/collecting-ringers
- https://www.bankless.com/talking-ringers-with-dmitri-cherniak
- "Art Blocks After Dinner Mints w/ Dmitri Cherniak" podcast, May 2021.
"""
from __future__ import annotations
from typing import ClassVar
import numpy as np
# --------------------------------------------------------------------------- Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/art_blocks/CherniakRingers/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from art blocks
Chromie Squiggle (Snowfro / Cherniak — Squiggles)
art_blocks · CherniakSquiggles
An implementation of the squiggle-generation kernel used in Snowfro's *Chromie Squiggle* (Art Blocks #0, November 2020) — the on-chain generative-art project that launched the Art Blocks platform itself and was the work Dmitri Cherniak cited (alongside *Genesis*) as his inspiration for Ringers.
Genesis (DCA — Day-Zero Art Blocks)
art_blocks · DcaGenesis
An interpretation of DCA's *Genesis* (Art Blocks #1, November 2020) — one of three Day-Zero collections (alongside Snowfro's Chromie Squiggle and Jeff Davis's Construction Token) that minted in the first 24 hours of the Art Blocks platform.
Hobbs Flow Field (Tyler Hobbs — Incomplete Control / Fidenza)
art_blocks · HobbsFlowField
The canonical perlin-noise flow-field algorithm described by Tyler Hobbs in his 2020 essay 'Flow Fields', and the algorithmic backbone of his Art Blocks Curated works *Incomplete Control* (Bright Moments, 2021) and *Fidenza* (Art Blocks, 2021).
Hobbs Watercolor Blob
art_blocks · HobbsWatercolorBlob
Layered translucent Gaussian blobs with watercolor-style alpha falloff.
Hobbs Watercolor Edge (Tyler Hobbs — Soft Textures / Watercolor)
art_blocks · HobbsWatercolorEdge
An implementation of Tyler Hobbs' 2017 'watercolor' technique: a recursive polygon-deformation algorithm whose midpoints are jittered by Gaussian noise across many passes, then stacked with low alpha (4% per layer, 30–100 layers total) to produce the soft, ink-bleed look of wet pigment on paper.
Penne 80s Vector (Aaron Penne — outrun perspective wireframe)
art_blocks · Penne80sVector
The 80s-synthwave outrun grid, the visual aesthetic Aaron Penne references in his generative-art practice (notably in *Apparitions* and his broader body of work).