Magical recessive / no coat effect
Particle
A horse that trails something as it moves — flames, souls, snow, hearts,
portal motes, a shrieker’s mark. Forty variant alleles at one
locus, which makes it by a wide margin the largest gene in the mod, and
the reason it is one locus rather than forty genes is the whole design: a horse
has two copies of the chromosome, so it shows at most two, ever,
and choosing which two is the game. The whole locus is recessive to its
own wild type — one copy of n and the horse trails
nothing at all.
Crossing two of them
It paints nothing
All 87 outcomes are wild types, so affectsCoat() is false, the locus
is out of the texture key, and GenotypeCatalog collapses all 861
combinations to a single entry — forty alleles for no catalogue
growth at all, the trick sex,
milk and verdant
already use.
Unlike those two, though, there is no visibility gap here: the whole gene is the thing you can see. It is the answer to the complaint milk and verdant both attract — an effect a player can watch without having to test for it.
Its gene carrot
- Gene key
- horsegenetics.particle
- Priority
- 150 (magical band)
- Alleles
- 40 variants + n — see the table
- Combinations
- 861, all carryable — 87 outcomes
- Outcomes
- wild, 40 single, 46 codominant double
- Shows when
- neither copy is
n— see below - Default allele
- n
- Wild frequency
- 0.15% per homozygote, 0.04% per codominant pair — about 7.8% of founders trail something, and no founder is a carrier
- Founder draws
- 1 × nextFloat()
- Coat effect
- none, ever
- Emission
- while moving on the ground, 20% of ticks, 1–4 particles a firing
Nothing has watched a horse trail anything. Forty particle ids is forty chances for one to read badly at horse scale, and the body sites have never been looked at on a scaled horse. The recessive rule and the carrier-free founder table are newer still, and the thing to check for those is simply that wild particle horses turn up at roughly one in thirteen. Checklist on To be verified.
One copy of n and the locus is silent
Rflm/n is a horse that trails nothing. Not a fainter
flame, not a smaller one — nothing, and it is indistinguishable from a
plain horse. It takes two variant copies to see anything at
all.
That is the owner’s call, and it is the rule everything else on this page follows from. A particle is a thing you breed for: a locus this wide where one lucky allele showed would put something on far too many horses, and would make the interesting half of the gene — finding the same allele twice — worth nothing.
The locus asks for agreement before it draws anything at all. Two
copies of the same allele, or two alleles of one family — and nothing else. Two
variant alleles that are not codominant partners are simply
two carriers: a Dst/Soul horse trails nothing, and
passes both on.
Until then, two variants that were not partners showed the
lower-ranked of the pair and hid the other. It sounded like the
thing that made a locus this wide breedable — a horse trailing dust
might be hiding a soul, and only its foals would say so — but look at
what it actually put in front of a breeder: a dust horse was either
Dst/Dst or Dst over any of the other
thirty-nine alleles, it looked exactly the same either way,
and no amount of looking told you which you had. That is the one thing a
breeding game must not do. Silence is the honest answer, and it costs
nothing: the founder table already excluded these pairs
for precisely this reason, so no wild horse ever was one. They arise only
from breeding, where the pedigree explains them.
Declaration order survives, but it is no longer a dominance rank.
The alleles are declared in it because AllelePair canonicalises on
Allele.order(), and that is what makes copy(0) and
copy(1) address the two halves of a codominant pair in a fixed order
— which matters, because each half draws its own colour and its own place on
the horse.
n is an off switch and it beats everything — and now so is any
allele without its partner beside it.
| Combination | What you see |
|---|---|
n/n | nothing |
Rflm/n | nothing — a silent carrier |
Rflm/Rflm | flames |
Rflm/Csmk | flames and campfire smoke — one family |
Rflm/Prtl | flames only; the portal is carried and hidden |
Codominance is by family
Every allele belongs to at most one family, and two different alleles of one family both show at once — in two different colours, from two different places on the horse. Nine families cover twenty-nine of the forty alleles and produce the locus’s 46 double outcomes; the other eleven alleles belong to no family and never stack with anything.
| Family | Alleles | Doubles |
|---|---|---|
burn | Smflm Rflm Bflm Smbflm + Wtsmk Smk Wtsmk2 Csmk | 28 |
dst | Dst Dst2 Dst3 | 3 |
str | Clrstr Whtstr Grnstr | 3 |
swrl | Bwswrl Whtswrl Bkswrl | 3 |
life | Chrylf Hrt Soul | 3 |
sklk | Sklk Sklk2 Sklk3 | 3 |
rain | Rain Rain2 | 1 |
prtl | Prtl Prtl2 | 1 |
spk | Ornspk Blspk | 1 |
The flames and the smokes are one family of eight, not two of four.
Any -flm stacks with any -smk as well as with its own
kind, which is 28 of the 46 doubles all by itself — get that grouping wrong
and most of the locus’s double outcomes quietly disappear. A unit test pins
it.
Two alleles whose tokens look related but are not: Dstrn
(enchanting glyphs) is not a dst, and Lmstr (totem
sparks) is not a str. Both are ungrouped, on purpose — the
family is about what the particle is, not what the token spells.
Everything you can see about it is epigenetic
The allele names a particle and nothing else. Everything else is stored on the allele copy that carries it and read by name:
| # | Value | Range | Used by |
|---|---|---|---|
| 1 | Colour | a bright hue (HairPattern.randomBrightColour) | dust, fading dust, all three swirls, ambient swirl; a param-less type (cherry petals, sculk…) ignores it |
| 2 | Second colour | the same | fading dust, the only particle that goes from one colour to another |
| 3 | Body site | head, spine, hooves, front hooves, back hooves, tail | every particle |
| 4 | Count | 1–4 per firing | every particle |
| 5 | Data | [0, 1) | a shriek’s delay, a sculk vibration’s travel time — whatever else a particle takes |
Every value is stored whether or not this particular particle uses it, so a variant that starts or stops caring about its second colour costs nothing and moves nothing. This used to be a fixed draw order, and the particle locus is the gene that paid for that lesson: the position of a draw was the meaning of each number, so a conditional draw quietly changed every horse in every save. Values are read by name now and the hazard is gone.
So two horses that are both Rflm/Rflm are not the same horse: one trails
four red flames off its front hooves, the other one green flame off its tail. And
because each copy of a codominant pair carries its own draw, the two halves are
independent — red flames off the front hooves and blue smoke off the
tail is one horse, and nobody wrote that combination down.
A foal that inherits the copy inherits the exact number, the way magic body size and mane colour do. That is what makes a particular look worth breeding from rather than worth re-rolling.
The machinery it needed
Abilities used to be a pure function of the genotype
(AbilityContribution), which is right for every gene where the alleles
fix the behaviour — two Hlr/Hlr horses heal identically, and
should. This locus is the case that cannot express, so it is the first
EpigeneticAbilityContribution: the same interface one
layer along, handed an GeneEpigenetics so it can read
copy(0) and copy(1) separately. It is the exact twin of
what EpigeneticTraitContribution did for the body, and
GeneEpigenetics moved from common/trait/ to
common/genetics/ so both sides could use it without the two packages
depending on each other.
HorseAbilities.activeFor gained an Epigenome overload,
and the translator’s per-horse cache is now keyed on both
code strings — keyed on the genotype alone it would have handed one horse
another horse’s colours.
The emitter verb grew with it:
a second colour, a count, a spare data number, and five new body
sites beside the four single-point anchors it had. All of it is usable
from a gene file today, which is the property the shared vocabulary was chosen for.
Every wild horse at this locus is one you can see
The founder table is not the random-mating shape, and that is
deliberate. It lists the forty homozygotes at 0.15% each and the
forty-six codominant pairs at 0.04% each, and nothing else. No
X/n carrier. No cross-family Dst/Bflm quietly sitting on
a soul flame nobody can see.
A locus that only expresses when both copies agree makes the carrier invisible, and a founder population full of invisible carriers is a locus run in the dark: you cannot see what a horse has, so you cannot choose what to pair it with, and every particle anyone gets is an accident.
Putting the wild horses on the expressing combinations puts the alleles where a breeder can find them — what you catch is what you watched it do. The carriers then appear exactly where they belong, one generation down, in the foals of a caught horse bred to a plain one.
The cross-family heterozygotes are excluded for the same reason and
not because they are impossible: Dst/Bflm is a perfectly
legal horse and breeding produces one. It is simply never a horse the wild
hands you.
In aggregate that is about 7.8% of wild horses trailing something, while any one named particle is roughly one horse in six hundred and sixty and any one double is one in twenty-five hundred. Meeting a particle horse is a good day; meeting the one you were looking for is a find.
The forty alleles
In declaration order. That order fixes which half of a codominant pair is
copy(0); it is not a dominance rank, and where two
alleles are not in the same family neither of them shows.
| # | Allele | Shows as | Particle | Family |
|---|---|---|---|---|
| 1 | Dst | Dust | dust | dst |
| 2 | Dst2 | Fading dust | dust_color_transition | dst |
| 3 | Clrstr | Glow motes | glow | str |
| 4 | Rain | Rain splash | rain | rain |
| 5 | Smflm | Small flame | small_flame | burn |
| 6 | Rain2 | Water wake | fishing | rain |
| 10 | Skl | Trial omen | trial_omen | — |
| 20 | Wtsmk | White smoke | white_smoke | burn |
| 30 | Smk | Smoke | smoke | burn |
| 31 | Wtsmk2 | White ash | white_ash | burn |
| 34 | Prtl2 | Reverse portal | reverse_portal | prtl |
| 41 | Bwswrl | Spell swirl | effect | swrl |
| 43 | Whtswrl | Ambient swirl | entity_effect | swrl |
| 44 | Lmstr | Totem sparks | totem_of_undying | — |
| 50 | Rflm | Flame | flame | burn |
| 51 | Bflm | Soul flame | soul_fire_flame | burn |
| 52 | Chrylf | Cherry petals | cherry_leaves | life |
| 53 | Dst3 | Dust plume | dust_plume | dst |
| 54 | Lava | Lava embers | lava | — |
| 60 | Smbflm | Copper flame | copper_fire_flame | burn |
| 65 | Raid | Raid omen | raid_omen | — |
| 66 | Sklk | Sculk charge | sculk_charge_pop | sklk |
| 67 | Sklk2 | Sculk vibration | vibration | sklk |
| 68 | Sklk3 | Sculk soul | sculk_soul | sklk |
| 69 | Shrk | Shriek | shriek | — |
| 72 | Ornspk | Spawner sparks | trial_spawner_detection | spk |
| 73 | Blspk | Ominous sparks | trial_spawner_detection_ominous | spk |
| 74 | Snw | Snowflakes | snowflake | — |
| 75 | Whtstr | Electric sparks | electric_spark | str |
| 80 | Prtl | Portal motes | portal | prtl |
| 83 | Ooze | Ooze | item_slime | — |
| 84 | Note | Notes | note | — |
| 85 | Snc | Sonic ring | sonic_boom | — |
| 88 | Dstrn | Enchanting glyphs | enchant | — |
| 90 | Hrt | Hearts | heart | life |
| 91 | Dig | Sculk debris | block (sculk) | — |
| 95 | Grnstr | Growth motes | happy_villager | str |
| 97 | Csmk | Campfire smoke | campfire_cosy_smoke | burn |
| 98 | Bkswrl | Evoker swirl | instant_effect | swrl |
| 99 | Soul | Souls | soul | life |
| — | n | wild type | none | — |
Ten of them are not the particle they were named after
The list this gene was designed from uses Bedrock particle names, and ten of them have no Java equivalent in 26.1.2. Each was mapped to the nearest real particle, and the substitutions are recorded here because the allele tokens still carry the original intent:
| Allele | Named after | Java particle used |
|---|---|---|
Wtsmk2 | magnesium_salts | white_ash |
Smbflm | small_soul_fire_flame | copper_fire_flame — new in 26.1.2, a genuinely third flame colour |
Sklk2 | sculk_sensor_redstone | vibration, aimed at the horse |
Ooze | oozing_emitter | item_slime |
Dig | warden_dig | block carrying a sculk state |
Grnstr | crop_growth_emitter | happy_villager |
Bkswrl | evoker_spell | instant_effect |
Skl | trial_omen_ambient | trial_omen |
Rain2 | water_wake | fishing (the same particle, renamed) |
Prtl2 | portal_reverse_particle | reverse_portal |
Two alleles were cut rather than substituted.
Bigflm (mobflame_emitter) and Cndlflm (candle) both land
on a particle another allele already has — flame and
small_flame — and Java flames are
SimpleParticleTypes carrying neither a colour nor a scale, so there
would have been no way to tell the pairs apart. Two alleles a player cannot tell
apart are worse than two alleles that do not exist, so the list is forty rather
than forty-two.
Why one locus and not forty genes
Forty independent two-allele genes would let a horse carry all forty at once, and then the interesting question — which of these does this horse trail — stops having an answer. Every serious line converges on a horse emitting everything, and the fortieth gene is worth nothing because the horse was already covered in particles.
One locus with forty alleles says the opposite, and says it structurally rather than by a rule anyone has to enforce. A horse has two copies of chromosome whatever-this-is, so it can carry two of these and no more; a third is not rare, it is impossible. It is exactly the argument that folded dominant white and sabino into KIT, at forty times the scale.
common/genetics/genes/ParticleGene.java