def g56_lode(rng):
"""Lode — a sparse vein: nearly every cell is bare ground, a scattered few erupt.
A field lays the whole ground as usual, calibrated so it spends the full
ramp. Wherever that same field crosses a high percentile the cell becomes a
"lode": a stack of shrinking marks climbs from the cell's own ground step
up toward the ramp's lightest step, so a handful of cells carry all the
incident and everything else stays flat, undisturbed ground.
"""
N = rng.choice([25, 30, 40, 50])
steps = rng.randint(5, 10)
primitive = rng.choice(["squares", "dots", "mixed"])
c = Canvas(N, rng.choice(PALETTE_NAMES), steps, "lode", primitive)
f = Field(rng, rng.choice(["mesh", "linear", "radial", "weave", "bilinear"]),
warp=rng.uniform(0.0, 0.5), steps=steps)
c.ground_from(f, dither=rng.random() < 0.3)
vals = sorted(f.raw((i + 0.5) / N, (j + 0.5) / N) for i in range(N) for j in range(N))
frac = rng.uniform(0.04, 0.12)
cut = vals[int(len(vals) * (1 - frac))]
nrings = rng.randint(3, 6)
shrink = rng.uniform(0.6, 0.8)
tilt = rng.uniform(0.0, 30.0)
for j in range(N):
for i in range(N):
u, v = c.uv(i, j)
if f.raw(u, v) < cut:
continue
if c.room() < nrings * 2 + 2:
continue
base = f.idx(u, v)
cx, cy = c.center(i, j)
w = c.C * rng.uniform(0.85, 0.98)
use_dots = primitive == "dots" or (primitive == "mixed" and rng.random() < 0.5)
for r in range(nrings):
t = r / max(1, nrings - 1)
k = min(steps - 1, base + round(t * (steps - 1 - base)))
size = w * (1 - t * shrink)
if use_dots:
c.dot(cx, cy, size / 2, k)
else:
ang = r * tilt
c.sq(cx - size / 2, cy - size / 2, size, size, k,
rot=ang if ang else None)
return c