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_INper G3, 1 inWILD_G2_ONE_INper 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
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.
| Allele | Copy state | Greying | Melanoma |
|---|---|---|---|
| N | normal | none | baseline |
| G2 | duplication | slower | lower |
| G3 | triplication | faster | higher |
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.
| Pair | dosage | Outcome | Drawn as |
|---|---|---|---|
N/N | 0 | wild | its base colour, for life |
N/G2 | 1 | grey-slow | dark steel to mid dapple |
N/G3, G2/G2 | 2 | grey | the ordinary dapple grey |
G2/G3 | 3 | grey-fast | light grey |
G3/G3 | 4 | grey-rapid | near 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
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.
dosage | Window | Reads as |
|---|---|---|
| 1 | 0.06 … 0.52 | dark steel → mid dapple |
| 2 | 0.28 … 0.74 | the ordinary dapple grey |
| 3 | 0.50 … 0.90 | light grey, dapples fading |
| 4 | 0.68 … 1.00 | near 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.
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:
- works out how dark each texel currently reads
(
0.55×red + 0.95×black); - writes that darkness back as black pigment, scaled by how far this horse’s greying has gone;
- 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.
| Region | What the coat does | How 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. |
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.
| Draw | Range | What it does |
|---|---|---|
| where in the window | 0 … 1 | Position 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 spacing | 2.8 … 5.0 body units | Size of the dapples. The body is about 22 units long. |
| dapple strength | 0.5 … 1 | Contrast 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 retention | 0 … 1 | How 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.26 | Whether the mane and tail run ahead of or behind the body. |
| chubari roll | < 0.18 | Whether this horse carries chubari spots. |
| chubari seed offset | — | Their own lattice, so the spots are not the dapples in disguise. |
| bloody roll | < 0.07 | Whether 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).
// 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.
| Chance | What it is | How 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:
| Tier | Reached by |
|---|---|
melanoma-risk-1 — raised | dosage 1–2 on a red or agouti coat |
melanoma-risk-2 — high | dosage 3–4, or dosage 1–2 on a black-based coat |
melanoma-risk-3 — highest | dosage 3–4 on a black-based coat |
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 with | Difference |
|---|---|
| Dominant white | Present from birth, and pink skin under the white. |
| Double cream | Born cream, blue eyes, pink skin. |
| Roan | A stable mix of white and coloured hairs, not a progressive one. |
| Silver | Dilutes black; the pale mane is there from birth. |
| Dapple grey | A 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.
common/genetics/genes/GreyGene.java,
common/coat/pattern/GreyCoat.java