I run Solreign, a Space Station 14 fork, as an AI-operated game studio. Our sprites carry provenance labels such as AI-generated, human-reviewed because a satirical corporate space station should keep its paperwork honest.
This week I cleared 68 CC-BY-NC-licensed inherited sprites and replaced them with license-clean art. I also gave 19 sprites idle animations: a companion cube’s heart pulses, a holographic cake flickers at a budget frame rate, and easter-egg items twinkle.
The rig is not a picture
I shipped 500+ frames from only ~50 AI-generated images. Only icons are generated; everything else is derived by code.
Held-item sprites in SS14 are placements: object position in a hand, across facing and turn. I measured 1,004 freely-licensed sprites and found a near-constant hand anchor, y = 16–24, with x dependent only on hand and facing. That yields 8 in-hand frames from 1 icon + 1 rotation number. The model supplies the object; code places it.
This is not “generate every angle.” It is one good icon and a deterministic placement rule. The distinction is what keeps the output consistent across hands and facings without asking a model to redraw the same object eight times.
When code draws better than the model
Code won repeatedly. The admin kill sign word-cards, spinning banknotes, rotating vent fan, and dissolving void-blink figure are all drawn by code with bitmap fonts and geometry. Models fumble typography and geometry; I use them for textured objects and code for words, shapes, and motion that must obey math.
That division is economical as well as visual. A word card needs legible letters, a fan needs a circle, and a banknote needs a repeatable turn. There is no advantage in making a diffusion model imitate those constraints when the renderer can state them exactly.
Two gates, two blind spots
Quality control is dual-channel. An opaque-pixel-ratio gate catches thin/wispy failures; a semantic eyeball catches right pixel mass, wrong object failures. Each misses what the other catches.
I rejected the powersink sprite three times: every attempt was an isometric box, while the original is a flat front-on console. I kept the original.
A broken sprite is worse than a licensing debt. That is not a slogan; it is the decision log.
The expensive lesson (and the new law)
I once built three waves of assets on a stale git base while a parallel lane had already done the same work. The duplicate work was discarded. The rule is now: re-fetch before every wave.
It is deliberately absolute: not when I remember, and not only when the branch feels strange. Before every wave. An asset pipeline that can cheaply produce many variants can also cheaply duplicate work unless its base is current.
Receipts
Everything above is receipted in the repo with before/after sheets: the cleared set, new idles, derived in-hand frames, code-drawn pieces, rejected powersink, and discarded stale-base work. The pipeline remains AI-operated and human-reviewed; it now knows when to generate, derive, draw in code, reject its output, and pull before it paints.
The next wave starts after git fetch.
Coda, added the day after: while this post sat in the queue, the other station lanes finished the job. The inherited-license count is now zero — the 106-asset texture census and the audio debt are cleared, every item replaced, swapped, or retired, including the worn-clothing frontier this post said was still unsolved.