Skip to content
Sample of Cherniak Nibbles (Dmitri Cherniak cell-eating cellular automata)

hobbs_cherniak_penne_deep · CherniakNibbles

Cherniak Nibbles (Dmitri Cherniak cell-eating cellular automata)

A cellular-automata growth algorithm in the spirit of Dmitri Cherniak's body of work — small 2D shapes ('nibbles') that grow by selectively removing neighbours. Each nibble is a connected component of grid cells; at every step a nibble picks one of its boundary cells and grows by 1 pixel in a direction biased by a Perlin-noise 'growth preference' field. If the new pixel would collide with another nibble or the canvas edge, the nibble 'dies' — its growth halts. The visual is an asymmetric Voronoi-like tessellation: irregular polygonal cells with hand-drawn edges (because the growth is stochastic, not perfectly radial), each painted with its own muted Cherniak-style colour. Cherniak describes his practice as 'automation as artistic medium' (LACMA, 2021), and the nibble-on-grid kernel is the simplest example of that ethos: a small local rule producing a complex global pattern.

Original: https://www.dmitricherniak.com

▶ 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.

Family
hobbs_cherniak_penne_deep
Source
hobbs_cherniak_penne_deep
Evolution
growth
Render
filled_blocks
Complexity
medium
Agents
24
Year
2024
Author
Dmitri Cherniak (algorithmic homage)

Math essence

Maintain an occupancy grid O of size (H, W) initialised to -1 (empty). At step t: pick an alive nibble n uniformly at random. For each cell c in n's cells, find the empty 4-neighbours and score them by alignment with the local growth-preference direction d(c) = (cos(2*pi*perlin(c)), sin(2*pi*perlin(c))). Greedily add the best-aligned empty neighbour to n (with 25% probability take the second-best for stochastic variation). If n has no empty neighbours, mark it dead.

Parameters

Name Type Default Range Description
dim int 600 200–1500 Square canvas side length (px).
grid_step int 3 1–12 Cell size (px) of the underlying grid.
num_seeds int 24 1–200 Number of seed nibbles to start.
steps_per_frame int 500 1–5000 Number of growth steps per step() call.
growth_noise_scale float 0.06 0.01–0.5 Perlin spatial frequency of the growth-preference field.
start_radius int 2 0–12 Initial radius (in grid cells) of each seed.
max_steps int 6000 100–50000 Maximum number of growth steps.
palette_mode str nibble null–null 'nibble' / 'random' / 'field' — per-nibble, per-pixel, or noise-field colour.
background tuple 240,236,226 null–null Background RGB colour (Cherniak's cream).

Reference

First 60 lines of reference.py. Full source: library_external/hobbs_cherniak_penne_deep/CherniakNibbles/reference.py

"""CherniakNibbles — Dmitri Cherniak cell-eating cellular automata.

A homage to Dmitri Cherniak's algorithmic style of *Nibbles* —
small 2D shapes that "nibble" through a grid of cells by
selectively removing neighbours.  Each nibble is a Voronoi-like
growing cell: at every step it picks a random cell on its
boundary, grows by 1 pixel, and stops if the new pixel would
collide with another cell or the canvas edge.

Cherniak describes his generative practice (LACMA, 2021):

    "One question is at the heart of Dmitri Cherniak's practice
     – what are the possibilities of automated art? Using
     algorithms, he crafts intricate abstract artworks that vary
     in mood and design."

The Nibbles kernel we implement:

    1. Initialise a 2D grid of "live" cells (a low-density
       starting layout: a few seeds at random positions, or a
       single block in the centre).
    2. Maintain a list of "nibbles" — each is a connected
       component of live cells with a known boundary.
    3. At each step, pick a nibble uniformly at random, then
       pick one of its boundary cells, and grow the nibble by
       1 pixel in a direction chosen by a noise-driven "growth
       preference" field (so different nibbles grow in different
       preferred directions, producing asymmetric forms).
    4. If the new pixel would collide with another nibble or
       the canvas edge, the nibble "dies" — its growth halts.
    5. Repeat for many steps.  The result is a grid of
       asymmetric 2D forms, each shaped by its growth history.

This is essentially an asymmetric Voronoi tessellation driven
by cellular-automata growth.  The visual is a tessellation of
irregular polygonal cells, like a Voronoi diagram but with
boundaries that look slightly noisy / hand-drawn (because the
growth is stochastic, not perfectly radial).

Reference:
- https://www.dmitricherniak.com
- https://www.youtube.com/watch?v=HoMt5vXmtP0  (LACMA interview)
- Voronoi tessellation: https://en.wikipedia.org/wiki/Voronoi_diagram
"""
from __future__ import annotations

from typing import ClassVar

import numpy as np


def _noise_2d(perm: np.ndarray, x: np.ndarray, y: np.ndarray) -> np.ndarray:
    """Tiny value-noise sampler (we don't need full Perlin here)."""
    # Hash-based pseudo-Perlin, returning values in [-1, 1].
    xi = np.floor(x).astype(np.int64) & 255
    yi = np.floor(y).astype(np.int64) & 255
    xf = x - np.floor(x)
    yf = y - np.floor(y)
    h = perm[(perm[xi] + yi) & 255]
    gx = ((h & 1) * 2 - 1).astype(np.float64)

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/hobbs_cherniak_penne_deep/CherniakNibbles/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from hobbs_cherniak_penne_deep

Sample of Cherniak Constellations (Dmitri Cherniak point-cloud + graph)

Cherniak Constellations (Dmitri Cherniak point-cloud + graph)

hobbs_cherniak_penne_deep · CherniakConstellations

A pseudo-random point cloud with connecting lines filtered by distance, producing graph-like emergent forms.

View →
Sample of Hobbs Color-Field Overlay (Tyler Hobbs compositional method)

Hobbs Color-Field Overlay (Tyler Hobbs compositional method)

hobbs_cherniak_penne_deep · HobbsColorFieldOverlay

Hobbs's compositional method of choice: combine TWO independent fields — a Perlin flow field that drives the *trajectory* of a set of line segments, and a Gaussian-blurred colour field that drives the *colour* and *opacity* of those segments.

View →
Sample of Hobbs QLIQUE (Tyler Hobbs — QQL dense-streamline tangle)

Hobbs QLIQUE (Tyler Hobbs — QQL dense-streamline tangle)

hobbs_cherniak_penne_deep · HobbsQLIQUE

A dense tangle of curves where every curve is a streamline through a Perlin flow field, in the visual spirit of Tyler Hobbs's 2022 QQL release (with Dandelion Mane).

View →
Sample of Hobbs Spirograph (Tyler Hobbs — Petal Loops / Elektroanima)

Hobbs Spirograph (Tyler Hobbs — Petal Loops / Elektroanima)

hobbs_cherniak_penne_deep · HobbsSpirograph

A rotating-circular-arc trail in the spirit of Tyler Hobbs's *Petal Loops* (2020) and *Elektroanima* (2020) — works described by Hobbs as 'looping taken to an excessive level.' M rotating points (default 8) are connected by a closed polyline that morphs each frame as the whole ring rotates by a small angle around a central anchor.

View →
Sample of Penne Imprecise Balance (Aaron Penne stacked-blocks column)

Penne Imprecise Balance (Aaron Penne stacked-blocks column)

hobbs_cherniak_penne_deep · PenneImpreciseBalance

A column of stacked rectangular blocks where each block is rotated by a seed-derived angle.

View →
Sample of Penne Ringers (Aaron Penne concentric ring extrusion)

Penne Ringers (Aaron Penne concentric ring extrusion)

hobbs_cherniak_penne_deep · PenneRingers

Penne's take on the *Ringers* idiom (best known from Cherniak's Art Blocks release, 2021): concentric rings extruded along the Z axis, rotated about a common axis, projected to 2D.

View →

See all hobbs_cherniak_penne_deep artworks →