10 Million Combinations: The Math Behind Procedural Pixel Art
When you click “Randomize” on a procedural art generator, you probably don’t think about the math that makes each result feel unique. But behind every pixel mech, procedurally generated face, or random dungeon layout, there’s a combinatorial system quietly multiplying possibilities. In this post, we’ll break down exactly how procedural pixel art achieves massive variety from simple rules – and why determinism is the secret ingredient that makes it all practical.
The Combinatorial Explosion
The core math behind procedural avatar generators is straightforward multiplication. If you have a single category – say, head shape – with 10 options, you get 10 possible results. Add a second category (eyes) with 10 options, and you have 10 x 10 = 100 combinations. Each new category multiplies the total.
MechGen uses 7 independent part categories, each with 10 variations:
- Head: Block, Dome, Visor, Horned, Flat, Round, Angular, Crown, Skull, Trapezoid
- Eyes: Dots, Wide, Visor, Cyclops, X-Eyes, LED Strip, Slant, Pixel, Angry, Scanner
- Antenna: None, Spike, Dual Rods, Dish, Blade, Orb, V-Shape, Radar, Halo, Periscope
- Body: Standard, Tank, Slim, Barrel, Armored, V-Torso, Crate, Hex, Orb, Pillar
- Arms: Standard, Claws, Cannons, Thin, Bulky, Blades, Tentacles, None, Drills, Shields
- Legs: Standard, Treads, Digitigrade, Hover, Spider, Wheels, Stompers, Mono, Stilts, Pogo
- Accessory: None, Jetpack, Shield, Chest Light, Shoulder Missiles, Back Vent, Energy Core, Wing Fins, Antenna Array, Tail
The formula is simply:
10 x 10 x 10 x 10 x 10 x 10 x 10 = 10^7 = 10,000,000
Ten million unique mechs from just 70 distinct parts. That’s the power of combinatorics – small inputs create enormous output spaces.
Color Palettes Push It Further
But part selection is only half the story. MechGen ships with 12 curated color palettes, each defining 5 color roles: primary body color, secondary detail color, accent highlights, eye color, and background. Each palette transforms the same mech silhouette into a completely different character.
When you factor in palettes, the real design space becomes:
10^7 parts x 12 palettes = 120,000,000 visually distinct mechs
And since users can also pick custom colors for each role, the practical number of possible outputs is effectively unlimited. The 12 curated palettes exist to guarantee that randomly generated mechs always look cohesive – a constraint that actually increases the perceived quality of random results.
Why Determinism Matters
Random generation is easy. Deterministic generation is what makes procedural art actually useful.
MechGen’s fromSeed() function takes any string – a username, an email, a project name – and always produces the exact same mech. Call it on any browser, any device, any operating system, and the result is identical. This is what makes seed-based generation powerful for real applications:
- AI agents can generate a consistent avatar from their name without storing image files
- Multiplayer games can derive player avatars from user IDs without a central image server
- Chat platforms can display the same avatar everywhere without syncing assets
How Seeded Random Generation Works
The technical implementation uses two classic algorithms chained together:
Step 1: String Hashing. The input string is converted to a numeric seed using a hash function. Each character’s code point is folded into an accumulator with bit shifts and additions, producing a single integer that represents the string.
Step 2: Linear Congruential Generator (LCG). That integer seeds a pseudorandom number generator. An LCG is one of the oldest and simplest PRNGs – it uses the formula:
next = (a * current + c) mod m
Each call to the seeded random function advances the internal state and returns a value between 0 and 1. MechGen calls this function once per part category to select an index (0-9), and once more to select a palette (0-11).
The key property of an LCG is that it’s entirely determined by its seed. Given the same starting integer, the sequence of “random” numbers is always identical. This means fromSeed("Atlas") will always pick the same head, eyes, antenna, body, arms, legs, accessory, and palette – on every machine, every time.
// Deterministic: always the same mech
MechGen.fromSeed("my-bot-name");
// Also deterministic: same seed, same result
MechGen.fromSeed("my-bot-name"); // identical output
Trade-offs of LCG
LCGs are not cryptographically secure. Their sequences are predictable, and the distribution isn’t perfectly uniform across all applications. But for avatar generation, these weaknesses don’t matter. You don’t need unpredictability – you need repeatability. An LCG is fast, simple to implement in any language, and produces sequences with enough variation to look random to human eyes across millions of combinations.
More sophisticated PRNGs like Mersenne Twister or xorshift128+ offer better statistical properties, but they add complexity without meaningful benefit for this use case. The simplicity of an LCG also means it’s trivial to re-implement in other languages if you want to reproduce the same mech generation in a backend service or mobile app.
How This Compares to Other Procedural Art Systems
Procedural generation has a long history across different domains:
- Identicons (used by GitHub and Gravatar) use hash-based generation but with much simpler visual output – typically symmetric geometric patterns. The design space is large but the visual variety feels limited because the structural rules are so constrained.
- NFT avatar projects like CryptoPunks use a similar layered-parts approach, but with rarity weighting – some traits are deliberately scarce. MechGen uses uniform distribution, so every combination is equally likely.
- Roguelike terrain generation uses cellular automata or Perlin noise, which are continuous rather than categorical. These systems produce smooth, organic variation rather than discrete part selection.
- Generative face tools (like the square face generators that inspired MechGen) prove that the layered-parts model works well for character avatars specifically, because humans naturally parse faces and characters as compositions of distinct features.
The layered-parts approach hits a sweet spot for avatars: it’s simple enough to run client-side with zero dependencies, deterministic enough for distributed systems, and expressive enough that 10 million combinations genuinely feel distinct.
The Design Challenge: Making Every Combination Look Good
The hardest part of procedural art isn’t generating variety – it’s ensuring quality across all possible outputs. With 10 million combinations, you can’t manually review each one. The system has to be designed so that every combination is at least acceptable.
MechGen handles this through several constraints:
- Fixed canvas grid: All parts are drawn on a 64x64 pixel canvas with a consistent coordinate system. Parts are designed to occupy specific regions, so a head always sits above a body regardless of which specific head and body are selected.
- Layered draw order: Parts are rendered back-to-front (accessory, legs, body, arms, head, antenna, eyes), ensuring that foreground elements correctly overlap background elements for every combination.
- Curated palettes: The 12 built-in palettes ensure that randomly generated mechs have harmonious colors. Every palette is tested against multiple part combinations to verify readability.
- Shading from single values: The
darken()andlighten()helper functions derive shadow and highlight colors from each base hex value, so depth and dimension are consistent regardless of the palette.
These constraints reduce the raw freedom of the system, but that’s the point. Good procedural generation is about defining a possibility space where every point is a valid, appealing result – not about maximizing randomness for its own sake.
Try It Yourself
Head to the MechGen generator and click Randomize a few times. Each click samples one point from that 10-million-combination space. Or type a seed string into the bot mode input and watch the same string always produce the same mech. That consistency across chaos is what makes procedural generation such a powerful tool for developers, designers, and anyone who needs unique visual identity at scale.