From 516e263c777de8cd40e49d859e7797890640d87e Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Sun, 14 Jun 2026 04:03:39 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B4=D0=B8=D0=B7=D0=B0=D0=B9=D0=BD=20?= =?UTF-8?q?=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D1=8B=20=D0=B6=D0=B8=D0=B2?= =?UTF-8?q?=D0=BE=D1=82=D0=BD=D1=8B=D1=85=20(=D0=B7=D0=BE=D0=BE=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Полный план зоологии на генетическом фундаменте: 7 столпов (гены, жизненный цикл, размножение, здоровье по модели RimWorld, мозг/интеллект, нужды, настроение), моддинг данными, фазы A1-A8 и экологический горизонт. Co-Authored-By: Claude Opus 4.8 --- docs/животные.md | 466 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 docs/животные.md diff --git a/docs/животные.md b/docs/животные.md new file mode 100644 index 0000000..9162caa --- /dev/null +++ b/docs/животные.md @@ -0,0 +1,466 @@ +# Животные (зоология) + +> Статус: **A1 реализована**, остальное по плану. Это живой план — правится по мере +> реализации фаз A1–A8. Стиль и правила — как в [концепте](concept.md) и [модах](mods.md). +> +> **A1 (готово):** тип дефа `Animal` (`AnimalDef : PawnDef`) + `animals.json` (олень); +> 8 животных генов в `genes.json`; `AnimalPhenotype`/`AnimalOrganism`; `AnimalSet` +> (шаблон генома вида) + `AnimalFactory`; детерминированный спавн стада оленей по суше в +> `WorldScene` с рендером и тинтом меха по гену; консольная команда `animal `. +> Проверено: `--check-content` (7 типов дефов, 28 генов). Визуальная проверка (олени в мире, +> команда `animal Deer`) — вручную: «Новый мир» → консоль. + +## Видение + +Животные — следующая большая система после генов. Главный принцип: животное живёт по +**тем же законам, что и растение** — гены → признаки (фенотип) → поведение систем, — +но разворачивает их в полноценную зоологию: двуполое размножение с вынашиванием, +здоровье по модели RimWorld (части тела, органы, кровь, болезни), мозг и интеллект, +нужды и настроение. Цель прежняя: **эмерджентность** (динамика популяций, отбор, +пищевые цепи складываются из правил, а не скриптуются) и **наблюдаемость** (всё видно +в мире, HUD, инспекторе, консоли). + +Первое показательное животное — **олень** (богатый набор текстур: ♂/♀/детёныш/труп). + +## Опора на существующий фундамент + +Ничего из перечисленного не строим заново — переиспользуем: + +- организм-агностичный `GeneDef`, управляемый `Genome` (диплоидные аллели), + `Genome.Breed(мать, отец, mutationChance)`, `Phenotype.Compute`, `GenomeTemplate` + (шаблон вида, ср. `PlantSet.BuildTemplate`); +- формульный движок и regex-группы (`gsum('Gene.*')`) для производных признаков; +- движковый `UtilityAi`, `ResponseCurve`, `Suitability.Trapezoid`; +- день/ночь, сезоны, климат, террейн `water`, `ProductDef`; +- паттерн компонентов растений: `…Organism { Genome; Phenotype Traits }`, + `…Growth { species, stage, ageDays }`, `…Needs`, `…Brain`, `AppearanceSystem` (sim→`Sprite`). +- Friflo допускает managed-ссылку в `IComponent` (доказано `Genome`/`Tilemap`) — + поэтому `Health`/`Pregnant` несут managed-объекты. + +## Принцип моддинга: всё расширяется данными + +Главное требование — **система должна целиком модифицироваться через моды без правки +кода**. Для этого: + +1. **Никаких C#-`enum` для видового контента.** Виды, части тела, органы, способности + (capacities), болезни, нужды, мысли — это **дефы со строковыми id**, интернируемые + в int при загрузке (ровно как уже сделано с `geneId`). Enum нельзя расширить модом — + строковый id можно. +2. **Формулы вместо констант** везде, где можно (как `effects` у генов): модер меняет + баланс формулой в дефе, а не пересборкой. +3. **Реестр поведенческих действий** (`actionId → исполнитель-код`). Деф нужды/ИИ + ссылается на `actionId`. Граница честная и в духе проекта (движок без сэмпла, + фичи демонстрируются игрой): **комбинировать готовые кирпичи — мод; принципиально + новое поведение — код + деф.** +4. **Patch-система (фаза G5)** уже позволяет модеру менять чужие дефы по regex + (например, «всем хищникам +агрессия»). +5. Любой деф переопределяется одноимённым из позднего мода; локализация — в `Languages`. + +Итог: модер добавляет новый вид зверя, орган, болезнь, нужду или мысль одними JSON-файлами. + +## Геном животного + +Животные гены живут в `genes.json` рядом с растительными (один организм-агностичный +тип `Gene`). Предлагаемый набор (числовые, если не сказано иное): + +| Группа | Гены | +|---|---| +| Тело/метаболизм | `GeneMaxBodySize`, `GeneMetabolism`, `GeneMoveSpeed`, `GeneBloodVolume`, `GeneVision`, `GeneInsulation` (мех/терморегуляция) | +| Жизненный цикл | `GeneMaturityAge`, `GeneLifespan` (есть), `GeneGestationDays`, `GeneLitterSize` | +| Органы | `GeneHeartEfficiency`, `GeneLungCapacity`, `GeneImmunityGain`, `GeneHealRate`, `GenePainTolerance` | +| Мозг | `GeneBrainSize` → признак `brainSize` (см. «Мозг и интеллект») | +| Поведение | `GeneAggression`, `GeneSociability`, `GeneActivityPattern` (дневной/ночной/сумеречный) | +| Среда | переиспользуем `GeneOptimalTemperature/Tolerance/Cold/HeatHardiness` — звери тоже мёрзнут/перегреваются через ту же трапецию | +| Морфология | `GeneFurColor` (тинт спрайта, как `leafHue`), `GeneSex` (дискретный, см. ниже) | + +**Пол выводится из диплоидности бесплатно.** Локус с аллелями {X=0, Y=1}: самка = XX, +самец = XY. При `Genome.Breed` мать может отдать только X (у неё нет Y), отец — X/Y +поровну → потомок XX/XY ровно 50/50, **без спец-кода в скрещивании**. У гена пола +`mutationChance: 0` (как у `GeneFruitSeason`), чтобы X не мутировал в Y. + +> Тонкость генерации (не скрещивания): обычный `Generate` дискретного гена выбрал бы +> два аллеля независимо и мог бы выдать невозможный **YY**. Поэтому пол особи-основателя +> назначается явно — XX или XY (по 50/50) — а дальнейшее наследование корректно само. + +Признаки собираются в `AnimalPhenotype.FromTraits(traits)` — зеркало `PlantPhenotype`. +Организм: `AnimalOrganism { Genome; AnimalPhenotype Traits; int Generation }` (поколение = +max(род.) + 1, у основателей 0 — для `popstats` и видимого дрейфа). + +## Жизненный цикл и стадии роста + +Зеркало `PlantGrowth`: `AnimalGrowth { species, stage, ageDays }`. Стадии задаются +данными в дефе вида: `Embryo` (в утробе) → `Baby` → `Juvenile` → `Adult` → `Senior`, +пороги из генов (`MaturityAge`, `Lifespan`). `AnimalGrowthSystem` двигает стадию, +масштабирует `sizeCells`, меняет спрайт/набор текстур (Baby ↔ ♀/♂). Стадия `Senior` +повышает шанс возрастных hediff и смерти — стык со здоровьем. + +> **Путь смерти по фазам.** Чтобы на A4 (размножение) популяция не взрывалась без +> убыли, простая **смерть по старости и от голода/жажды (деспавн)** появляется уже в A3. +> На A5 она «апгрейдится»: смерть идёт через здоровье (возрастные hediff, истощение, отказ +> органов) и оставляет **труп** вместо деспавна. + +## Нужды и ИИ + +Обобщаем `PawnNeeds` (одна энергия) → `AnimalNeeds`: голод, жажда, сон, секс (0..1). + +- скорости падения из `GeneMetabolism` × размер (масштаб по Клайберу: ∝ size^0.75); +- **голод** — ест растения/продукты. **Поедание реально воздействует на сущность + растения** (важно для контура ёмкости среды): выедает накопленные плоды + (`Fruiting.RipeFruit`) и/или убавляет биомассу/стадию растения; перевыпас может убить + растение. **Диета** (`AnimalDef.diet`) — список съедобного: теги растений/`ProductDef` + (для будущих хищников — живая добыча/мясо/трупы), плюс способ (выедание плодов vs выпас); +- **жажда** — пьёт на клетках террейна `water`; +- **сон** — спит в неактивную фазу суток (`GeneActivityPattern`): дневные ночью и т.д.; +- **секс** — удовлетворяется размножением. + +ИИ разбит на **два слоя — выбор и исполнение**: + +1. **Выбор** — `AnimalDecisionSystem` на движковом `UtilityAi`: из активных нужд выбирает + действие `FindFood / FindWater / Sleep / SeekMate / Wander(default)` (готовые + `ResponseCurve`) и пишет его + цель в `AnimalBrain { Action; Target; DecideIn }`. + Действия и нужды описаны дефами `NeedDef` (decay-формула, `minBrain`). +2. **Исполнение** — отдельный слой систем (реестр `actionId → исполнитель`, см. «Принцип + моддинга») доводит выбранное действие до результата по схеме **найти цель → дойти → + выполнить → удовлетворить нужду**: + - *Eat*: ближайшее съедобное (плод/биомасса) → подойти → съесть (убавить растение) → ↑ сытость; + - *Drink*: ближайшая клетка `water` → подойти → попить → ↓ жажда; + - *Sleep*: остановиться → спать → ↓ усталость; + - *Mate*: подходящий партнёр → сблизиться → акт → `Pregnant` + сброс `Mating`; + - *Wander*: движение по умолчанию. + Без этого слоя нужда только падает, но не исполняется. + +**Передвижение и поиск цели.** Движение к цели — рулевое смещение к точке (реюз +`Transform2D` + `WanderSystem`/`SeparationSystem` для обхода препятствий: стволы деревьев, +другие звери), без полноценного A* на старте. Вода непроходима для сухопутных → `Drink` +целит клетку суши у кромки воды. «Ближайшее съедобное/вода/партнёр» — **пространственный +запрос по сетке/тайлмапу** с радиусом из `Vision`/`Sight` (не O(n²)); ничьи в «ближайшем» +разрешаются детерминированно (по id сущности). + +> Порядок фаз: формальный **гейтинг нужд интеллектом — фаза A7**. В A2 у оленя просто +> полный набор нужд зверя (тир 4); поле `minBrain` уже пишем в дефы, но активируется оно +> на A7 (см. «Мозг и интеллект»). + +## Размножение (млекопитающие) + +Главное отличие от растений — двуполость и отложенное во времени вынашивание: + +1. **Влечение и гон (через хедиф).** Нужда `Mating` есть **круглый год** на низком фоне. + В брачный сезон вида на взрослых вешается **хедиф `Rut` (гон)**, который поднимает + влечение (множитель на рост `Mating` / снижение порога действия). **Только под `Rut` + влечение переходит порог `SeekMate` → вне сезона зачатия фактически нет**, хотя нужда + формально существует. Хедиф снимается с концом сезона и **виден в инспекторе** (как + любой hediff). Это унифицирует сезонность с hediff-механизмом, а не городит спец-флаг. +2. **Спаривание → беременность.** Два взрослых разного пола сближаются (действие `Mate`) → + акт → у самки появляется `Pregnant : IComponent { Genome FatherGenome; float + ConceivedDay; float GestationDays; int LitterSize }` — managed-ссылка на геном отца + (оплодотворение = «слепок» отца). Беременность повышает метаболизм (голод) и снижает + `Moving`. (Можно реализовать и как hediff, но держим компонентом ради managed-ссылки + на геном отца.) +3. **Роды.** По достижении срока спавним `LitterSize` детёнышей, каждому + `Genome.Breed(мать, отец, mutationRate)`, стадия `Baby`, рядом с матерью. Лактация/ + опека — опционально после. + +Стратегии r/K выводятся из генов: мелкие (заяц) — большой помёт, короткая жизнь; +крупные (олень/медведь) — мало потомства, долгая жизнь. + +**Решённые параметры (A4):** +- **Гон = хедиф `Rut`** (а не «нужда растёт в сезон»): навешивается в брачный сезон + `GeneBreedingSeason` (как `fruitSeason`, 0..3) — у **оленя осень** (→ роды весной к + обилию корма); у r-стратегов (заяц) — круглогодично/частый гон. Под `Rut` влечение + переходит порог действия; вне `Rut` зачатия нет. +- **Hediff-каркас рождается здесь (A4).** Гон — первый хедиф, поэтому в A4 появляется + лёгкий каркас: контейнер `Health`/`HealthState` со списком хедифов, `HediffDef` со + стадиями и модификаторами, навешивание/снятие по триггеру. A5/A6 расширяют его + частями тела, кровью, болезнями. +- **Триггер акта** — взрослые, разный пол, у обоих `Mating > 0.6`, рядом (1–2 клетки), + самка не беременна, оба не спят/не убегают. +- **Послеродовый кулдаун** — самка не зачинает снова до родов + восстановления; + самец восстанавливается быстро → **полигиния** (один самец кроет нескольких самок). +- **Выбор партнёра (половой отбор)** — НЕ в A4: на старте берётся ближайший подходящий; + предпочтение по размеру/здоровью/настроению добавим позже отдельной итерацией. + +## Здоровье — полная модель RimWorld + +### Данные (дефы) + +- **`BodyDef`** — дерево частей. У части: `coverage` (доля тела → вес попадания), + `parent`, `maxHp` (масштаб от размера тела), флаги (`vital`, `solid`, `skinCovered`), + **вклады в capacities** `{ breathing: 0.5, consciousness: 1.0, moving: 0.25, … }`. + Пример (олень): `body → torso → (heart, lungs×2, liver, stomach, kidneys×2, spine), + head → (brain, eyes×2, ears×2, jaw), legs×4 → hooves`. +- **`HediffDef`** — *всё* есть hediff (рана, потеря части, болезнь, имплант, можно и + беременность): `stages` с порогами по severity; стадия задаёт `capMods` + (offset/factor/setMax по capacity), `painOffset/painFactor`, `bleedRate`, для болезней — + параметры иммунитета. +- **`CapacityDef`** — общий каталог способностей строковыми id: `Consciousness, Moving, + Manipulation, Sight, Hearing, Breathing, BloodPumping, BloodFiltration, Digestion, + Metabolism` (расширяемо модом). Это **каталог**, а не обязательный набор: вид имеет + лишь те способности, в которые вкладываются части его `BodyDef` (у копытного оленя нет + `Manipulation` — некому вкладываться). + +### Компонент + +`Health : IComponent { HealthState State }` — managed-класс (как `Genome`): +`List` (деф + текущий hp), `List` (severity, привязка к части, +иммунитет), кэш `Capacities`, `Pain`, `BloodLevel`, `Dead`. + +> Контейнер растёт по фазам: **рождается в A4** с одним лишь `List` (под гон-хедиф +> `Rut`); части тела, кровь, capacities и `Dead` добавляются в A5, болезни/иммунитет — A6. + +### Расчёт capacities (обобщённая дата-модель) + +Способности зависят друг от друга, считаем в порядке зависимостей: + +1. `BloodLevel` (0..1) ← запас минус кровопотеря; +2. `BloodPumping` ← сердце × BloodLevel; `Breathing` ← лёгкие × BloodLevel; + `BloodFiltration` ← печень/почки; +3. `Consciousness` ← мозг × BloodPumping × Breathing × (1 − болевой штраф); +4. `Moving` ← ноги/позвоночник × Consciousness × BloodPumping; `Sight` ← глаза × + Consciousness; `Digestion` и пр. — домножаются на вышестоящие. + +Формула одна и общая: `capacity = Σ(вклады работающих частей × partHp/maxHp) × +вышестоящие capacity`. **Без хардкода на каждую способность** — новую способность +вводит деф. Каждая capacity — множитель на действия: `Moving`→скорость, `Sight`→радиус +поиска, `Digestion`→скорость насыщения, `Consciousness`→интеллект и сам факт сознания. + +### Кровь — как hediff (реалистичная модель RW) + +Кровопотеря = hediff `BloodLoss` (severity 0..1). Кровоточащие раны поднимают её через +`bleedRate`; без кровотечения медленно рассасывается; severity = 1 → смерть; влияет на +`BloodPumping`/`Consciousness` через `capMods`. `GeneBloodVolume` масштабирует скорость +роста severity (больше крови → медленнее теряет). + +### Болезни и иммунитет (гонка) + +severity болезни растёт за день; параллельно растёт иммунитет (0..1) со скоростью из +стата (зависит от `BloodFiltration`, отдыха, сытости, `GeneImmunityGain`). Иммунитет→1 +раньше = выздоровел; severity→летальный порог раньше = смерть. Голодный/раненый зверь +борется с болезнью медленнее. + +### Смерть + +Триггеры: разрушена `vital`-часть (мозг/сердце), `Consciousness ≤ порога`, +`BloodLevel = 0`, летальная severity болезни, старость (возрастные hediff: катаракта, +больная спина, деменция, закупорка артерий + шанс смерти от старости). На смерти: +стоп-ИИ, переход в труп. + +### Тик + +Медленный «health tick» раз в игровой час + событийный пересчёт при уроне. +Детерминизм: привязка к игровому времени, не к FPS. + +### Источники урона в v1 + +**Почти никаких.** Строим весь каркас (части, кровь, capacities, hediff-framework, условия +смерти), но не вводим *травмирующих* источников. На старте (A1–A2) смерть только **от +старости**. + +Порядок источников урона по фазам: **истощение/обезвоживание** — уже в **A3** (простое +правило «нужда=0 дольше N дней → смерть», замыкает контур ёмкости среды; в A5 +переоформляется в hediff истощения) → **температура** (гипотермия/тепловой удар, hediff на +той же трапеции, что у растений) → **болезни** (A6) → **хищничество** (горизонт). + +## Труп и разложение + +Труп — отдельная сущность с `Corpse { RotDays; Stage }`. Конвейер (скорость зависит от +температуры/сезона — реюз климата): + +``` +Fresh ──→ Rotting ──→ Skeleton ──→ (исчезает) + │ │ │ + │ разделка │ разделка └─ остаётся ProductBone + └──────────┴─→ ProductMeat (кол-во ∝ GeneBodySize) + опц. ProductLeather +``` + +- свежий/гниющий можно **разделать** → мясо (объём от размера тела) + шкура; + спрайт `Dessicated_*` (для оленя уже есть) на стадии Rotting; +- **скелет** — финальная стадия разложения (как просили, скелет — часть процесса): + мясо уже не получить, остаются кости (`ProductBone`); +- после скелета труп **исчезает в ничто**. На будущее — возврат плодородия в почву + (ниточка к растениям, опционально). +- мясо/кости/падаль → кормовая база будущих хищников и падальщиков. + +Новые продукты: `ProductMeat`, `ProductBone`, `ProductLeather`. + +**Спрайт скелета — нужен настоящий (решено).** В проекте костяных/скелетных текстур +нет (проверено) → это **ассет-задача**: создать/найти спрайт скелета (желательно +универсальный + по-видовой при наличии), путь вида `things/pawn/animal/deer/Skeleton_*`. +До появления ассета стадию Skeleton можно временно рисовать обработкой `Dessicated_*`, +но финальная версия требует своего спрайта. + +## Мозг и интеллект + +`GeneBrainSize` → признак `brainSize`. **Эффективный интеллект** = `brainSize × +Consciousness` — т.е. повреждение/болезнь мозга, боль, кровопотеря динамически снижают +интеллект (сильная связка со здоровьем). + +Интеллект **гейтит набор нужд и действий**. У `NeedDef`/действия поле `minBrain`: +активный набор особи = те, у кого `minBrain ≤ brainSize`. **Без enum** — шкала +непрерывная, тиры ниже лишь ярлыки для авторов контента (числа порогов — контент, +правятся модом). `brainSize` нормирован 0..1. + +| Тир | `minBrain` | Кто | Что открывается | +|---|---|---|---| +| 1 — рефлекс | 0.00 | губки, простейшие | пассивный голод, реактивность | +| 2 — примитив | ~0.10 | насекомые, черви | голод; реактивное поведение | +| 3 — низший позвоночный | ~0.25 | рыбы, рептилии, амфибии | +жажда; простое избегание | +| 4 — зверь | ~0.45 | млекопитающие, птицы (**олень**, заяц, волк) | +сон, секс, Flee, SeekMate; **настроение**; факультативно стадность/память | +| 5 — умный (на будущее) | ~0.75 | приматы, врановые, люди | +социальные нужды, игра, любопытство, память о ресурсах, планирование, обучение, сложное настроение/отношения | + +Олень = **тир 4**. Настроение, сон и брачное поведение включаются с тира 4. + +## Настроение + +`Mood` (0..1) собирается **из двух источников** (решено): + +1. **Непрерывные состояния → в настроение напрямую** по кривой `ResponseCurve`: + уровни голода, жажды, усталости, боли (из здоровья), температуры вне комфорта. + Это не дискретные мысли, а текущий вклад нужд/состояния. +2. **События → `ThoughtDef { moodOffset, durationDays, trigger }`** (модель thoughts + RimWorld, данными): «дала потомство», «спарилась», «напилась после долгой жажды», + «потеряла детёныша» — временный сдвиг настроения с затуханием. + +Настроение есть только с тира 4 (зверь) — гейт интеллектом; у примитивных его нет. +Влияет на поведение (низкое → паника/бегство, не спаривается) и видно в инспекторе. + +## Ориентировочные числа для оленя (старт) + +Шкала времени мира: **год = 60 игровых дней**, сезон = 15 дней (для справки растения +живут ~160 дней). Числа — стартовая точка, балансируются при реализации; это значения +по умолчанию генома вида (`GenomeTemplate`), вокруг которых идёт разброс и мутации. + +| Параметр | Ген/поле | Значение | Заметка | +|---|---|---|---| +| Размер тела | `GeneMaxBodySize` | ♀ 1.4 / ♂ 1.6 sizeCells | как в текущих `DeerDoe`/`DeerBuck` | +| Продолжительность жизни | `GeneLifespan` | ~360 дн (~6 лет) | дольше растений, видно несколько поколений | +| Взросление (→Adult) | `GeneMaturityAge` | ~90 дн (~1.5 года) | Baby 0–20, Juvenile 20–90, Adult 90–~290, Senior 290+ | +| Срок беременности | `GeneGestationDays` | ~30 дн (2 сезона) | гон осенью → роды весной | +| Помёт | `GeneLitterSize` | 1 (изредка 2) | K-стратег | +| Сезон гона | `GeneBreedingSeason` | осень | у зайца — круглый год | +| Размер мозга | `GeneBrainSize` | ~0.45 (тир 4) | открывает сон/секс/настроение | +| Объём крови | `GeneBloodVolume` | ~1.0 (×размер) | масштабирует скорость кровопотери | +| Скорость | `GeneMoveSpeed` | ~1.1–1.3 | олень быстрый | +| Голод | `NeedDef` decay | полный голод за ~1.5 дн | по Клайберу ∝ size^0.75 | +| Жажда | `NeedDef` decay | полная жажда за ~0.75 дн | быстрее голода | +| Сон | `NeedDef` decay | суточный цикл | спит в неактивную фазу | + +## Идеи для реализма (бэклог) + +Опционально, по мере фаз — каждая ложится на дата-модель: + +- **Гон/брачный сезон** — хедиф `Rut`, навешиваемый в сезон, поднимает влечение (реализовано в A4). +- **Терморегуляция мехом** — `GeneInsulation` сдвигает температурную трапецию; + новорождённые мёрзнут сильнее. +- **Метаболизм по Клайберу** — расход ∝ size^0.75 (крупные едят больше абсолютно, + меньше на кг). +- **Циркадные ритмы** — дневные/ночные/сумеречные виды (`GeneActivityPattern`). +- **Стадность** — `GeneSociability`: стадные держатся группой (реюз `SeparationSystem` + + когезия) → эмерджентные стада. +- **Сезонный окрас** — арктические лиса/заяц/волк белеют зимой (текстуры `*_arctic` + есть) — сезонный свитч спрайта/тинта. +- **Половой диморфизм** — рога/размер у самцов (ген, проявляется при XY). +- **r/K-стратегии** — выводятся из `litterSize/gestation/lifespan`. +- **Инбридинг-депрессия** (продвинутое) — родственное скрещивание снижает fitness + через накопление рецессивных аллелей. +- **Память о ресурсах/территория** (для умных) — водопои, кормовые места. +- **Возврат нутриентов** — полное разложение трупа повышает плодородие клетки. + +## Новые типы дефов (для модеров) + +| Тип | Назначение | +|---|---| +| `AnimalDef : PawnDef` (подтип) | вид: геном-шаблон (ссылки на гены), `BodyDef`, диета, текстуры по стадиям/полу, размеры. Наследник `PawnDef` — существующие 9 животных-`PawnDef` остаются валидными; поведение на компонентах, не на типе дефа | +| `BodyDef` | дерево частей тела с coverage/parent/maxHp/флагами/вкладами в capacities | +| `HediffDef` | раны/болезни/состояния: стадии, capMods, боль, кровотечение, иммунитет | +| `CapacityDef` | именованная способность (строковый id) | +| `NeedDef` | нужда: формула расхода, `minBrain`, привязка к действию | +| `ThoughtDef` | мысль настроения: offset, длительность, условие-триггер | +| `ProductDef` (есть) | + `ProductMeat`, `ProductBone`, `ProductLeather` | + +CLR-классы — `src/LittleSim/Content/GameDefs.cs`; новый тип = класс + `RegisterType` в +`GameContent.Load` (см. [mods.md](mods.md)). + +## Отбор, экология и наблюдаемость + +Смысл генетики — чтобы за поколениями популяция **реально адаптировалась к климату +сида** (дрейф признаков под отбором). Чтобы это было видно (столп «наблюдаемость»): + +- **Команда `popstats `** — среднее и разброс ключевых признаков популяции + + счётчик поколений. Без неё отбор «есть, но невидим». Появляется, как только в мире + есть популяция (≈A1–A2), расширяется по мере добавления признаков. +- **Контур ёмкости среды (Лотка–Вольтерра через корм).** Даже без хищников травоядные + могут **выесть растения → голод → крах популяции → восстановление флоры → новый рост**. + Это бесплатная эмерджентность уже на A2, **если поедание реально уменьшает растения**. + Явно проверяем этот контур на A2 (поедание убавляет плод/растение, голод растёт при + нехватке корма). **Важно:** полный «крах» популяции требует **смерти от голода** — она + появляется в **A3** (простое правило). На A2 контур наблюдается частично (звери голодают + и тормозят, но не вымирают), полностью замыкается с A3. + +## Сквозные требования (каждая фаза) + +- **Детерминизм.** Любая случайность (спавн, выбор партнёра, мутации, выбор части под + урон, шанс инфекции) — из seeded `Random`, выведенного из сида мира (+ id сущности), + никогда `Random.Shared`. Один сид = воспроизводимый мир. Ничьи в пространственных + запросах («ближайший корм/вода/партнёр») разрешаются по id сущности, не по порядку обхода. +- **Сериализация — чек-лист по каждой фазе.** Каждая фаза сразу делает сейв/лоад своих + данных: A1 геном (уже умеет, geneId→Allele) → A3 стадия/возраст/пол → A4 беременность + (срок + **геном отца**) + список хедифов (гон `Rut`) → A5 здоровье (части тела, кровь, + capacities) + труп (стадия/таймер разложения) → A8 настроение/мысли. Пустой/старый + сейв — регенерируется, не крашит. +- **Sim/presentation split.** Системы симуляции пишут только компоненты; спрайт/тинт + (пол, стадия, мех, гниль) ставит `AppearanceSystem`. Никаких draw/UI из симуляции. + +## План реализации (фазы A1–A8) + +По аналогии с фазами генов G1–G5. Каждая фаза — отдельный коммит, дев-команда для +проверки, проверка через `--check-content` (где можно), и пункты сквозных требований выше. +**Вкладки инспектора добавляются по мере появления данных:** needs@A2, health@A5, mood@A8. + +1. **A1 — фундамент.** `AnimalDef` + животные гены + `AnimalPhenotype`/`AnimalOrganism` + + per-species `GenomeTemplate` + спавн оленя в `WorldScene` + рендер + команда + `animal `. +2. **A2 — нужды + ИИ (выбор + исполнение).** `AnimalNeeds` + `AnimalDecisionSystem` + (выбор) + **слой исполнения** (Eat/Drink/Sleep: найти→дойти→выполнить→удовлетворить) + + еда-растения / вода-террейн / сон по фазе суток + `AppearanceSystem`. **Проверить + контур ёмкости среды** (поедание убавляет растения → колебания). Команда `popstats`. +3. **A3 — жизненный цикл.** Стадии Baby→Adult→Senior, ген пола (XX/XY, генерация без + YY), спрайт по стадии/полу, **простая смерть по старости и от голода/жажды (деспавн)** + — последняя замыкает контур ёмкости среды. +4. **A4 — размножение.** Нужда `Mating` + **лёгкий hediff-каркас** + гон-хедиф `Rut` + (сезон) + исполнение `Mate` → `Pregnant` → роды через `Genome.Breed`. +5. **A5 — здоровье I.** `BodyDef`, части тела, кровь (hediff), capacities, **апгрейд + смерти**: через здоровье + **труп** с разложением до скелета (вместо деспавна A3). +6. **A6 — здоровье II.** Болезни/`HediffDef` с иммунитетом, боль. +7. **A7 — мозг/интеллект.** Ген→интеллект→гейт нужд/действий + обратная связь от + повреждения мозга. +8. **A8 — настроение.** `Mood` + `ThoughtDef` + вкладки инспектора (needs/health/mood — + `InspectPanel` уже умеет вкладки overview/genes/products). + +## После A8 — экологический горизонт + +То, ради чего вся глубина: превращает «зоопарк» в живую экосистему. Каждая фича опирается +на уже построенные системы. + +- **Хищный кластер.** Хищничество (волк→олень): диета = живая добыча; действие `Hunt` + (выследить → преследовать → атака → **урон через здоровье A5** → добить → съесть труп). + Это **первый «активный» (травмирующий) источник урона** для системы здоровья и + полноценная Лотка–Вольтерра с хищником. Рядом: **падальщики** (едят трупы Fresh/Rotting) + и **угроза/бегство** (хищник в радиусе `Sight` → страх → действие `Flee`, удар по + настроению; стадо снижает страх). +- **Родительская опека / импринтинг.** Детёныш ходит за матерью, голод гасится близостью + к лактирующей матери до ювенильной стадии; мать ведёт/защищает. Реализм + детёныши не + мрут от голода в одиночку. +- **Эпидемии.** Болезни (A6) распространяются по контакту/плотности → плотностно-зависимый + регулятор популяции (вспышки-крахи). Исход решает иммунитет (`GeneImmunityGain`). +- **Миграция.** При локальном истощении корма / некомфортном климате — уход к лучшим + клеткам (концепт: «голод+неурожай→миграция»). Эмерджентно из нужд + пространственного + поиска с большим радиусом. + +Сюда же тяготеют пункты бэклога: половой отбор (выбор партнёра), сезонный окрас, +инбридинг-депрессия, возврат нутриентов в почву. + +## Открытые вопросы + +- Конкретный список `ThoughtDef`-событий для оленя (набор и величины offset/длительности) + — детализируется при реализации A8. +- Ассет: создать/найти спрайт скелета (`things/pawn/animal/deer/Skeleton_*`) к фазе A5.