patterns — accretion

generator verdict no votes yet
source — auto/a002_accretion.g52_accretion
def g52_accretion(rng):
    """ACCRETION — a growth cluster built one cell at a time from a seed, each
    step adding the open edge cell most favoured by a fixed stickiness field, so
    growth chases the field's peaks instead of spreading evenly. Glyph weight at
    each cell comes from its final neighbour count: core reads solid, fingers
    reading light where the growth thinned out."""
    N = rng.choice([32, 40, 50])
    c = Canvas(N, "GLYPH", "glyph", "accretion", tiles=False)
    NX, NY = c.cols, c.rows
    occ = [[False] * NY for _ in range(NX)]
    dirs4 = [(1, 0), (-1, 0), (0, 1), (0, -1)]
    dirs8 = dirs4 + [(1, 1), (-1, -1), (1, -1), (-1, 1)]

    n_seeds = rng.choice([1, 1, 2, 3])
    seeds = set()
    tries = 0
    while len(seeds) < n_seeds and tries < 50:
        tries += 1
        seeds.add((rng.randrange(NX), rng.randrange(NY)))
    for (si, sj) in seeds:
        occ[si][sj] = True

    frontier = set()

    def open_around(i, j):
        for dx, dy in dirs4:
            ni, nj = i + dx, j + dy
            if 0 <= ni < NX and 0 <= nj < NY and not occ[ni][nj]:
                frontier.add((ni, nj))

    for (si, sj) in seeds:
        open_around(si, sj)

    nz = Value2D(rng, res=rng.choice([3, 4, 5, 6]))
    gamma = rng.uniform(1.0, 4.0)
    target = int(NX * NY * rng.uniform(0.30, 0.50))
    filled = len(seeds)

    while filled < target and frontier:
        items = list(frontier)
        weights = []
        for (i, j) in items:
            u, v = (i + 0.5) / NX, (j + 0.5) / NY
            weights.append(nz(u, v) ** gamma + 0.02)
        tot = sum(weights)
        r = rng.uniform(0.0, tot)
        acc = 0.0
        pick = items[-1]
        for it, w in zip(items, weights):
            acc += w
            if r <= acc:
                pick = it
                break
        i, j = pick
        occ[i][j] = True
        filled += 1
        frontier.discard((i, j))
        open_around(i, j)

    ramp_chars = ramp([".", ":", "+", "x", "o", "#", "▒", "▓", "█"])
    for i in range(NX):
        for j in range(NY):
            if not occ[i][j]:
                continue
            deg = 0
            for dx, dy in dirs8:
                ni, nj = i + dx, j + dy
                if 0 <= ni < NX and 0 <= nj < NY and occ[ni][nj]:
                    deg += 1
            k = min(len(ramp_chars) - 1, int(deg / 8.0 * (len(ramp_chars) - 1)))
            c.glyph(i, j, ramp_chars[k])
    return c
accretion-glyph-40-195f
accretion-glyph-40-195f
accretion-glyph-50-6c3c
accretion-glyph-50-6c3c
accretion-glyph-32-b839
accretion-glyph-32-b839
accretion-glyph-40-1827
accretion-glyph-40-1827
accretion-glyph-32-ca3e
accretion-glyph-32-ca3e
accretion-glyph-50-fdff
accretion-glyph-50-fdff
accretion-glyph-32-1cad
accretion-glyph-32-1cad
accretion-glyph-32-4671
accretion-glyph-32-4671
accretion-glyph-50-7250
accretion-glyph-50-7250
accretion-glyph-32-f551
accretion-glyph-32-f551

generator