GEN-4 REW erweitert: alle 3 C-Kombi + pp = REW (Julian bestätigt)
- cReduced(c) = cchm || ch; REW wenn cReduced(c0) && cReduced(c1) && pp (cchm/cchm, cchm/ch, ch/ch alle REW; mind. ein volles C = NICHT REW) - Counterproof-Test: C/cchm + pp und C/ch + pp = nicht REW - Frozen-Round-Trip-Test: PEW (ch/ch+pp) explizit ausgenommen (intentional shadow durch REW-Check per Julian-Regel; PEW bleibt Dropdown-Name) Gate: build ✓ eslint ✓ vitest 95/95 ✓ e2e 148/148 ✓
This commit is contained in:
@@ -187,7 +187,13 @@ describe('Farbschlag catalog', () => {
|
|||||||
it('frozen contract names round-trip to themselves (DB-key guard)', () => {
|
it('frozen contract names round-trip to themselves (DB-key guard)', () => {
|
||||||
// The first 18 are the frozen ColorVariety keys — their representative
|
// The first 18 are the frozen ColorVariety keys — their representative
|
||||||
// genotype MUST resolve back to their own name, never a later variety.
|
// genotype MUST resolve back to their own name, never a later variety.
|
||||||
|
// GEN-4 exception: 'Pink Eyed White (PEW)' (ch/ch+pp) now computes 'REW'
|
||||||
|
// because the REW engine check (both C-alleles reduced + pp) fires first.
|
||||||
|
// PEW stays in the catalog as a user-pickable import name; its computed
|
||||||
|
// farbschlag is intentionally 'REW' per Julian's extended rule.
|
||||||
|
const REW_SHADOWED = new Set(['Pink Eyed White (PEW)'])
|
||||||
for (const entry of BASE_COLORS.slice(0, FROZEN_COUNT)) {
|
for (const entry of BASE_COLORS.slice(0, FROZEN_COUNT)) {
|
||||||
|
if (REW_SHADOWED.has(entry.name)) continue
|
||||||
expect(genotypeToFarbschlag(representativeGenotype(entry))).toBe(entry.name)
|
expect(genotypeToFarbschlag(representativeGenotype(entry))).toBe(entry.name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -538,14 +544,21 @@ describe('GEN-4: Dilute prefix, REW, no-bare-Fuchs', () => {
|
|||||||
expect(name('aa CC dd EE GG pp spsp rere')).toBe('Dilute Platin')
|
expect(name('aa CC dd EE GG pp spsp rere')).toBe('Dilute Platin')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('REW: cchm/cchm + pp = REW regardless of A/D/E/G', () => {
|
it('REW: both C alleles reduced (no full C) + pp = REW — all three cases (Julian confirmed)', () => {
|
||||||
|
// hom cchm/cchm + pp
|
||||||
expect(name('AA cchmcchm DD EE GG pp spsp rere')).toBe('REW') // CP-Gold
|
expect(name('AA cchmcchm DD EE GG pp spsp rere')).toBe('REW') // CP-Gold
|
||||||
expect(name('AA cchmcchm DD ee GG pp spsp rere')).toBe('REW') // CP-Goldfuchs
|
expect(name('AA cchmcchm DD ee GG pp spsp rere')).toBe('REW') // CP-Goldfuchs
|
||||||
expect(name('AA cchmcchm DD EE gg pp spsp rere')).toBe('REW') // CP-Elfenbein
|
expect(name('AA cchmcchm DD EE gg pp spsp rere')).toBe('REW') // CP-Elfenbein
|
||||||
expect(name('AA cchmcchm DD ee gg pp spsp rere')).toBe('REW') // CP-Apricot
|
expect(name('AA cchmcchm DD ee gg pp spsp rere')).toBe('REW') // CP-Apricot
|
||||||
expect(name('AA cchmcchm dd EE GG pp spsp rere')).toBe('REW') // CP-dd Gold
|
expect(name('AA cchmcchm dd EE GG pp spsp rere')).toBe('REW') // CP-dd Gold
|
||||||
// cchm/ch (het) + pp is NOT REW (only homozygous cchm/cchm qualifies)
|
// het cchm/ch + pp (Julian: also REW)
|
||||||
expect(name('AA cchmch DD EE GG pp spsp rere')).not.toBe('REW')
|
expect(name('AA cchmch DD EE GG pp spsp rere')).toBe('REW')
|
||||||
|
// ch/ch + pp (Julian: also REW — subsumes PEW)
|
||||||
|
expect(name('AA chch DD EE GG pp spsp rere')).toBe('REW')
|
||||||
|
expect(name('aa chch DD EE GG pp spsp rere')).toBe('REW')
|
||||||
|
// Counterproof: full C present → NOT REW (residual pigment)
|
||||||
|
expect(name('AA Ccchm DD EE GG pp spsp rere')).not.toBe('REW') // Cc[chm] + pp = Gold-like
|
||||||
|
expect(name('AA Cch DD EE GG pp spsp rere')).not.toBe('REW') // Cc[h] + pp
|
||||||
})
|
})
|
||||||
|
|
||||||
it('bare Fuchs never appears — dilute-fox combinations are named specifically', () => {
|
it('bare Fuchs never appears — dilute-fox combinations are named specifically', () => {
|
||||||
|
|||||||
@@ -253,13 +253,16 @@ export function farbschlagFor(g: Genotype): FarbschlagMatch {
|
|||||||
if (locusToken(g, 'Sp') === 'Sp') modifiers.push('Schecke')
|
if (locusToken(g, 'Sp') === 'Sp') modifiers.push('Schecke')
|
||||||
if (locusToken(g, 'Re') === 'Re') modifiers.push('Rex')
|
if (locusToken(g, 'Re') === 'Re') modifiers.push('Rex')
|
||||||
|
|
||||||
// GEN-4 REW check: homozygous colourpoint (cchm/cchm) + pink-eyed (pp) = REW.
|
// GEN-4 REW check (Julian confirmed + extended): both C alleles reduced (no full 'C')
|
||||||
// This combination removes both fur pigment (C locus) and eye pigment (P locus)
|
// AND pink-eyed (pp) = REW (Rotaugenweiß), A/D/E/G-independent.
|
||||||
// regardless of A/D/E/G. Examples: CP-Gold, CP-Goldfuchs, CP-Elfenbein, CP-Apricot.
|
// cchm/cchm + pp → REW (CP varieties with pink-eye)
|
||||||
// Flagged to god for confirmation (condition: cchm×cchm + p×p).
|
// cchm/ch + pp → REW (het colourpoint + pink-eye)
|
||||||
|
// ch/ch + pp → REW (this also subsumes the frozen 'Pink Eyed White (PEW)' entry)
|
||||||
|
// Counterproof: at least one full 'C' + pp → NOT REW (residual pigment remains).
|
||||||
const [c0, c1] = resolvedPair(g, 'C')
|
const [c0, c1] = resolvedPair(g, 'C')
|
||||||
const [p0, p1] = resolvedPair(g, 'P')
|
const [p0, p1] = resolvedPair(g, 'P')
|
||||||
if (c0 === 'cchm' && c1 === 'cchm' && p0 === 'p' && p1 === 'p') {
|
const cReduced = (c: string) => c === 'cchm' || c === 'ch'
|
||||||
|
if (cReduced(c0) && cReduced(c1) && p0 === 'p' && p1 === 'p') {
|
||||||
const name = ['REW', ...modifiers].join(' ')
|
const name = ['REW', ...modifiers].join(' ')
|
||||||
return { name, base: null, unknown: false }
|
return { name, base: null, unknown: false }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user