Natural gene / phase 1

Grey — the coat that goes white

A horse is born its ordinary colour and then progressively grows white hairs until it is a steel, a dapple, a light or a near-white grey. Grey is a copy number, not a point mutation, and the number of copies is the rate: G3 is a triplication and fast, G2 a duplication and slow, and the four grey dosages are drawn at four different stages. It is the only gene that reads age, the only one that is a remap rather than a restriction, and the only coat gene that is also a health gene.

Crossing two of them

Health: an informational melanoma-risk condition, in three tiers

Where it is common

Breed changes the frequency of the alleles in the founder pool and nothing about what grey does once present — a G3 Andalusian and a G3 Quarter Horse follow the same rule. Breeds holds the tables; the wild pool outside a breed uses Hardy–Weinberg over the three alleles.

G3 is the broadly prevalent one and dominates the grey breeds: the Lipizzan and the Camargue (fixed grey), the Percheron, the Andalusian and Lusitano, the Arabian. G2 is real but breed-clustered, so only the populations the duplication was actually reported in carry it: the Andalusian, Connemara Pony, American Miniature, Mustang, Quarter Horse, Tennessee Walking Horse and Welsh Pony. (The reference also names the Mangalarga Marchador, which this mod’s catalogue does not carry.)

Its gene carrot

Gene key
horsegenetics.grey
Alleles
G3 G2 N
Outcomes
wild, grey-slow, grey, grey-fast, grey-rapid
Shows when
GreyGene.dosage ≥ 1 — painted on adults only
Default allele
N
Wild frequency
1 in GreyGene.WILD_G3_ONE_IN per G3, 1 in WILD_G2_ONE_IN per G2; Hardy–Weinberg over the three
Founder draws
1 × nextFloat()
Deterministic
no when expressed
Epi draws
1 long + 8 × nextFloat
Health
an informational melanoma-risk condition, in three tiers
Generator
coat.pattern.GreyCoat
Built, not yet seen in-game

The three-allele rework replaced a two-allele G/g grey with one flat progression roll. It compiles, is unit-tested and in the golden file, but no grey of any dosage has been looked at in a game — the checklist is on To be verified.

Three alleles, because the locus is a copy number

Grey is a copy-number variation in and around intron 6 of STX17 (syntaxin 17), with regulatory effects reaching neighbouring genes such as NR4A3. What varies between horses is how many copies of that stretch they carry, and a commercial copy-number test reports exactly that.

AlleleCopy stateGreyingMelanoma
Nnormalnonebaseline
G2duplicationslowerlower
G3triplicationfasterhigher

Either copy-bearing allele makes a horse grey, so in ordinary inheritance terms grey is autosomal dominant — not recessive, not codominant. But dominant does not mean the genotypes look alike. They differ in rate, and rate is dosage: G3 counts two, G2 counts one, and the sum runs 0 to 4.

PairdosageOutcomeDrawn as
N/N0wildits base colour, for life
N/G21grey-slowdark steel to mid dapple
N/G3, G2/G22greythe ordinary dapple grey
G2/G33grey-fastlight grey
G3/G34grey-rapidnear white

Inheritance is then just Mendel on three alleles. A horse carrying two grey alleles — G2/G2, G2/G3 or G3/G3 — passes one to every foal, so every foal is grey; a heterozygote passes it half the time. What the pedigree carries is not grey yes/no but which copy number, which is why the gene stores an allele pair and not a flag: a G2 line greys slowly and carries the lower risk, a G3 line greys fast and carries the higher one, and choosing between them is a real breeding decision.

A rate, without a clock

Settled

Horse aging is deliberately out of scope — it risks feeling bad for a player attached to a horse. Greying, though, is a rate, and a rate needs a timeline before it is a picture.

So the mod draws each dosage class at the stage that rate would plausibly have reached on an ordinary adult, and fixes it for life. A slow grey is a steel or dapple grey forever; a rapid grey is the near-white one. Nothing evolves in real time, and the horse a player bonded with does not change under them.

The option is not foreclosed. Reopening it means giving the composer a real age input, which today knows only adult vs foal — the windows below would become a rate and the age would pick the point on it. Nothing else in the design would have to move.

The dosage picks a window and the horse’s own epigenetics pick where inside it the horse sits. The windows overlap on purpose: individual variation inside a real genotype class is large enough that a slow grey and a fast one genuinely can meet in the middle. What is reliably true is the ordering of the means, and that is what GreyCoat.WINDOW encodes.

dosageWindowReads as
10.06 … 0.52dark steel → mid dapple
20.28 … 0.74the ordinary dapple grey
30.50 … 0.90light grey, dapples fading
40.68 … 1.00near white

Even the least-greyed adult keeps well short of its birth colour (KEEP_YOUNG = 0.46). With no age input, every grey adult has to read as a grey; a horse indistinguishable from a plain bay would just be a bay with a hidden flag on it.

Grey is a remap, and that is the whole point

Greying replaces pigmented hairs with white ones, and a mix of white and dark hairs reads neutral. So a grey has to land on the gradient’s zero-red column, the only place the LUT is actually grey.

Why scaling both pigments does not work

Scaling red and black together walks the sample down the gradient’s diagonal — and the diagonal runs through the golds. At an equal keep of 0.4 a black horse samples (150, 109, 56): a tan. That is why the old flat KEEP = 0.15 had to sit almost on top of white to look grey at all, and why every grey then looked like the same white horse.

So GreyCoat instead:

  1. works out how dark each texel currently reads (0.55×red + 0.95×black);
  2. writes that darkness back as black pigment, scaled by how far this horse’s greying has gone;
  3. keeps only a fading trace of the red.

What was underneath still shows: a greying chestnut ends lighter than a greying black, and a barely-greyed horse keeps a rose or steel cast. The stored base colour is untouched — grey is a display layer over a bay or a chestnut that remains a bay or a chestnut in its genotype, its code and its foals.

Regions do not grey together

A uniform mask over the whole horse is the thing that makes a rendered grey look like a recoloured decal. Real greying is regional, and the regions are correlated rather than independent — they all move with the same progression, but each has its own offset.

RegionWhat the coat doesHow it is drawn
Head White hairs round the eyes are the usual first sign, and the head stays among the palest areas the whole way through. headLead: a flat HEAD_LEAD = 0.34 over head, muzzle and ears, plus EYE_LEAD = 0.30 more on a radial falloff from the forehead (CoatRegions.faceMask, reach 3.2). A standing offset, not one that fades out.
Legs Grey along with the body but hold visible base colour longer. A ramp that is full at the hoof and gone by mid-cannon, scaled by 1 - progression — so it is the young greys that show dark legs under a light body.
Mane and tail Depigment on their own timing, ahead of or behind the body, and along their length. An independent stage, swung up to HAIR_STAGE_SWING = ±0.26 either way, plus a root-to-tip ramp (HAIR_ROOT_LEAD = 0.30).
Barrel, shoulder, hip The main readable surface, with regional variation. The body’s own stage, varied by the dapple field.
Skin, eyes, hooves Stay dark. A grey is not a dominant white and not a double cream. Untouched. Grey writes to no other gene’s channel.
A bug worth naming

The head used to be on the point-retention list — it took half a boost, holding colour on the one region a greying horse loses it from first. The sign was inverted. It now takes a headLead instead, and pointWeight covers only mane, tail, ears, muzzle and the lower legs.

Why the mane greys from the root

Greying is a change to hairs as they are produced, so the new hair at the root is whiter than the old hair further down. On a body texel that has nowhere to show; on a mane or a tail it has the whole length of the hair. The ramp runs along HairPattern.axesBySpan(skin, part)[1] — the same root-to-tip axis the midtstol is centred in.

The nine draws

Off the expressing grey copy’s epigenetics, in this order: nextLong() for the dapple field’s seed, then eight nextFloat()s.

DrawRangeWhat it does
where in the window0 … 1Position inside the dosage’s window, giving progress; keep = lerp(0.46, 0.10, p). Fixed for life. This is what makes one grey different from the next within a genotype class.
dapple spacing2.8 … 5.0 body unitsSize of the dapples. The body is about 22 units long.
dapple strength0.5 … 1Contrast between a dapple centre and the web around it, up to DAPPLE_DEPTH = 0.42. Scaled to peak mid-greying — a barely-started or almost-finished horse has little pigment left to vary.
point retention0 … 1How much longer mane / tail / ears / muzzle (full) and the lower legs (ramped) hold their colour. Scaled by 1 - progression.
hair stage swing−0.26 … +0.26Whether the mane and tail run ahead of or behind the body.
chubari roll< 0.18Whether this horse carries chubari spots.
chubari seed offsetTheir own lattice, so the spots are not the dapples in disguise.
bloody roll< 0.07Whether this horse carries a bloody shoulder.

DAPPLE_DEPTH is generous on purpose: most of a composed texel’s variation is the white template’s own shading, so the dapple field has to push harder than it looks like it should. Sample bakes put the field itself at a 21–29% lightness modulation on the mid greys, and about 5% on a nearly-white one.

The dapples

Dapples come from BodyNoise.cellDistance — distance to the nearest point of a jittered lattice, sampled in body space so the rings cross part seams without a join, and warped by a low-frequency BodyNoise.value so the lattice flows instead of gridding up. Near a lattice point is a dapple centre (lighter); out in the gaps is the web (darker).

common/coat/pattern/GreyCoat.java
// Warp the sample so the dapple lattice flows instead of gridding up.
double n  = BodyNoise.value(noiseSeed ^ 0x51L, x * warpScale, y * warpScale, z * warpScale);
double m  = BodyNoise.value(noiseSeed ^ 0x52L, z * warpScale, x * warpScale, y * warpScale);
double wx = x + (n - 0.5) * warp;
double wy = y + (m - 0.5) * warp;
double wz = z + (n - m)   * warp;

double d   = BodyNoise.cellDistance(noiseSeed, wx * scale, wy * scale, wz * scale);
float  web = (float) smoothstep(0.35, 0.78, d);   // 0 at a dapple centre -> 1 in the web
float  keep = lerp(keepDapple, keepWeb, web);

Chubari spots and the bloody shoulder

Two bounded variations on a fixed grey. Both are visual modifiers only — neither alters the genotype, the risk tier or what the horse passes on. They sit after the main grey pass in the same painter.

ChanceWhat it isHow it is drawn
Chubari spots 18% Rounded white patches scattered over a light grey. The dapples’ cellular field at a much larger cell size (CHUBARI_SPACING = 7), with a separate low-frequency selector picking which third of the cells are spots. Not drawn below CHUBARI_MIN_PROGRESS = 0.55: on a steel grey a white patch is just a dapple.
Bloody shoulder 7% A patch of retained base colour over the shoulder that never greys. An ellipse in barrel-fraction space with a noise-wandered edge, so it is a stain and not a decal. It lerps back toward the pigment that was there rather than painting over the grey — a bloody shoulder on a bay is bay, on a chestnut chestnut.

The selector for the chubari spots is deliberately sampled at a much lower frequency than the cells themselves. Sample it at the cells’ own frequency and it varies inside each cell and cuts it in half — which is exactly how manchado’s islands first came out as slivers.

Melanoma: reported, never simulated

The same STX17 change that removes pigment from hair drives melanocyte proliferation, which is why the two travel together. Grey horses carry a markedly raised lifetime risk of dermal melanoma — UC Davis reports over 70% of greys past fifteen, and published reviews commonly cite around 80%. In life the tail dock and perineum, the sheath or udder, the lips and the eyelids are where it shows. G3 carries more risk than G2, and a grey that is genetically non-agouti — black-based, where extension permits black pigment — carries more again.

GreyGene implements HealthContribution and emits one Condition.informational, with a tier from the copy number raised one step on a black-based coat:

TierReached by
melanoma-risk-1 — raiseddosage 1–2 on a red or agouti coat
melanoma-risk-2 — highdosage 3–4, or dosage 1–2 on a black-based coat
melanoma-risk-3 — highestdosage 3–4 on a black-based coat
The line, and why it is there

It is informational and nothing else: no stat is docked, no lesion is drawn, no horse dies of it, and it is not one of the two lethal paths.

That is the design, not a stub. Melanoma in life is a lifetime probability that mostly resolves as benign nodules on an old horse, and this mod has no age to hang a probability on. Docking health from every grey would assert a disease four greys in ten never get; drawing lesions would be worse, and the owner ruled painted melanoma out with aging. So the mod says what the DNA test says — this horse is in a raised-risk group, and here is how raised — and stops.

And whiteness is never a diagnosis. The tier is read off the copy number and the base coat, not off how pale the horse came out; a very light N/G2 and a dark G3/G3 both exist, and the risk follows the genotype.

Foals

restrict no-ops when !ctx.isAdult(), so a grey foal is born its base colour and greys once grown. One wrinkle: isDeterministic cannot see the foal flag (only restrict gets the CoatBuildContext), so a grey foal is also treated as per-horse. It bakes its own texture, and that texture is identical to a non-grey foal’s. Harmless — just a few extra cache entries.

What grey is not

Not to be confused withDifference
Dominant whitePresent from birth, and pink skin under the white.
Double creamBorn cream, blue eyes, pink skin.
RoanA stable mix of white and coloured hairs, not a progressive one.
SilverDilutes black; the pale mane is there from birth.
Dapple greyA stage of grey, not a locus. It is the middle of the window above.

What was in the reference and is not here

The source note proposed a five-stage health pipeline — genotype, then appearance, then susceptibility, then an age-related chance of lesion onset, then lesion burden and severity with health effects. Stages 4 and 5 need an age clock and a per-horse disease-progression system, neither of which exists, so they are not built and are not stubbed. The Condition is the whole of it.

It also suggested vitiligo-like depigmentation round the eyes and mouth, and flea-bitten grey. Both are parked with aging: see the settled list.

Source: common/genetics/genes/GreyGene.java, common/coat/pattern/GreyCoat.java