From a441ed9763e9336bfaa032c2479473ddb0fea336 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Wed, 19 Aug 2026 22:27:20 +0300 Subject: [PATCH] Update documentation to enhance clarity on native language and skill generation - Revised `AGENTS.md` to specify that the same seed, map, name set, and native language must produce the same roster in tests. - Updated `protocol.md` to clarify that everyone in the school is generated with the selected native language, and related languages may appear at a low skill. - Enhanced `ai.md` to explain skill growth mechanics based on state and the introduction of minimum ranges for skills not yet acquired. - Improved `people.md` to detail the generation of skills and traits, emphasizing that not every person receives every skill and the implications of body attributes on skill acquisition. - Adjusted `projects.md` to reflect the inclusion of native language in roster generation, ensuring comprehensive documentation of project components. --- AGENTS.md | 4 ++-- docs/design/ai.md | 3 ++- docs/design/people.md | 53 ++++++++++++++++++++++++++++------------- docs/design/projects.md | 2 +- docs/protocol.md | 12 +++++++--- 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 16d6e7a..5dcd2db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -108,8 +108,8 @@ say so explicitly in the change description. - Simulation changes need a `GameClock` or `SchoolRegistry` test. They are fast and need no host. Putting a roster into `World` and ticking needs belongs there too. -- People generation belongs in `tests/HSchool.People.Tests`. Same seed, map and name set must - produce the same roster; the suite does not boot a host. +- People generation belongs in `tests/HSchool.People.Tests`. Same seed, map, name set and + native language must produce the same roster; the suite does not boot a host. - Timetable planning belongs in `tests/HSchool.Schedule.Tests`. Same staff, map and locks must produce the same table; the suite does not boot a host. - Walking and day plans belong in `tests/HSchool.Ai.Tests`. Same seed and map must produce the diff --git a/docs/design/ai.md b/docs/design/ai.md index 1133b66..31fb111 100644 --- a/docs/design/ai.md +++ b/docs/design/ai.md @@ -186,7 +186,8 @@ Осознанно мало: - **Навык растёт на уроке** — от предмета, с поправкой на черты и на то, в каком человек - состоянии. Голодный учится хуже. + состоянии. Голодный учится хуже. Если ключа ещё нет (химия в восьмом), рост начинается с + `Range.Min`, а не с нуля «как будто навык был всегда». - **Опоздание и прогул видны.** В кабинете 5Б на математике не двадцать три человека, а двадцать один, и карточка каждого говорит, где он. diff --git a/docs/design/people.md b/docs/design/people.md index d8426b9..ef1e818 100644 --- a/docs/design/people.md +++ b/docs/design/people.md @@ -138,7 +138,9 @@ Пять новых видов. Ссылки — строками `defName`, как везде. 1. **SkillDef** — навык. Диапазон, распределение при генерации, зависимость от возраста, - ограничения со стороны тела (см. ниже). + ограничения со стороны тела (см. ниже). Не каждый человек получает каждый навык: + `always` — у всех, предметы — по параллели ученика, `work` — только взрослым, + `adultChance` — шанс у взрослого поверх родного языка. 2. **TraitDef** — черта. Вес (частота), список несовместимых черт, ограничения по роли и возрасту, модификаторы навыков. 3. **BodyAttributeDef** — свойство тела. Либо число с распределением (рост, вес), либо выбор из @@ -153,14 +155,15 @@ | Вид | Ванильное содержание | | --- | --- | -| Навыки | Школьные предметы (математика, русский, литература, физика, история, физкультура…) и физические (ловкость, сила, выносливость) | +| Навыки | Школьные предметы, языки набора имён, общение, физические (ловкость, сила, выносливость) и рабочие (педагогика, медицина, кухня…) | | Черты | Около десяти для начала: усидчивый, рассеянный, задира, тихоня, лидер, лентяй, любопытный, вспыльчивый, добрый, аккуратный | | Тело | Рост, вес, цвет волос, цвет глаз | | Нужды | Сон, голод, туалет, общение | -Слои одинаковы у всех ролей. У неработающего родителя те же навыки и черты, что у ученика: урезать -их дешевле по памяти и дороже в коде — иначе каждое место, читающее навык, начинается с вопроса -«а есть ли он у этого человека». +Слои одинаковы у всех ролей: у родителя те же *виды* данных, что у ученика. Набор ключей +навыков — нет. Нет ключа — нет навыка, а не ноль: карточка его не показывает, урок, если +предмет всё же начался, стартует с `Range.Min`. Иначе первоклассник носил бы химию «для +полноты», а код всё равно спрашивал бы, есть ли она. ### Как тело ограничивает навыки @@ -181,9 +184,14 @@ } ``` -Генератор сначала бросает тело, потом навык, потом применяет ограничения как зажим. Порядок важен -и фиксируется: **тело первично**, навык подстраивается. Иначе один и тот же сид даст разных людей -в зависимости от порядка перебора. +Генератор сначала бросает тело, потом те навыки, которые человеку положены, потом применяет +ограничения как зажим. Порядок важен и фиксируется: **тело первично**, навык подстраивается. +Иначе один и тот же сид даст разных людей в зависимости от порядка перебора. + +Выдача навыков тоже фиксирована: `always` → родной язык школы → предметы параллели (ученик) → +лишние академические, рабочие и `adultChance` (взрослый) → черты и зажим тела → родственные +языки набора. Годовой набор добавляет только новые ключи предметов; уже выданные значения не +перебрасываются. Ограничения — не только вниз: «атлет не может быть совсем неловким» так же осмысленно, поэтому `min` есть наравне с `max`. @@ -208,6 +216,13 @@ **Один набор на школу.** Выбирается в диалоге создания рядом с модами и сохраняется в файле школы. Смеси с весами («80% славянских, 20% прочих») — не в этом срезе: они требуют UI для весов. +Набор несёт список языков, на которых здесь говорят (`nativeLanguages`). Школа выбирает **один** +при создании — это родной язык всех людей. Остальные языки списка часто появляются на низком +уровне (`relatedLanguageChance` и соседние поля на том же def): русскоязычный может понимать +белорусский. Уже выданный ключ — родной или предмет школы — не перезаписывается, поэтому +белорусский ученик сохраняет школьный русский, а не обрезанный «чуть-чуть». Шанс `0` оставляет +родственников выключенными (одноязычный пакет). + Набор имён **не связан с языком интерфейса**. Английский UI не превращает Иванову в Ivanova: язык интерфейса — про подписи кнопок, набор имён — про то, кто учится в школе. @@ -240,13 +255,15 @@ Protocol ← Server → Simulation → People → Content - **Не** зависит от Arch, ASP.NET и сокетов — как `Content` сейчас. - Отдаёт простые записи. Превращает их в сущности `World` уже `HSchool.Simulation`. -Так генератор тестируется без мира и без хоста: «этот сид + эта карта + этот набор имён → ровно -эти люди». Это единственный способ поймать регрессию в генераторе — глазами такое не проверяется. +Так генератор тестируется без мира и без хоста: «этот сид + эта карта + этот набор имён + этот +родной язык → ровно эти люди». Это единственный способ поймать регрессию в генераторе — глазами +такое не проверяется. ### Детерминизм Генерация детерминирована от **сида**, сид лежит в файле школы. Один сид + одна карта + один набор -имён = одна и та же школа, всегда. +имён + один родной язык = одна и та же школа, всегда. Если родной язык при создании не указан, +его выбирает тот же сид — повтор без поля даёт тот же язык. Сид у каждой семьи свой, выведенный из школьного: добавление тринадцатой семьи не должно менять первые двенадцать. Иначе тест на генератор ломается от любой правки порядка. @@ -268,7 +285,8 @@ Protocol ← Server → Simulation → People → Content Школа создаётся посреди учебного года (по умолчанию 3 апреля), поэтому при создании классы уже сформированы и возраст ученика соответствует его параллели: в N-й класс ходят те, кому -исполнилось N+6 до 1 сентября. +исполнилось N+6 до 1 сентября. Переход в следующую параллель **добавляет** навыки новых +предметов (английский с пятого, химия с восьмого) и не перебрасывает уже выданные. ## Просмотр @@ -285,7 +303,8 @@ Protocol ← Server → Simulation → People → Content - **Сортировки**: фамилия, возраст, параллель, должность. - **Пейджинг** обязателен: тысяча учеников — это три тысячи человек с семьями. - **Строка списка** — только лёгкое: ФИО, роль, класс или должность, возраст, пол. -- **Карточка** одного человека — тело, навыки, черты, нужды, семья со ссылками на родных. +- **Карточка** одного человека — тело, навыки (только те, что есть), черты, нужды, семья со + ссылками на родных. ## Масштаб @@ -357,16 +376,18 @@ Protocol ← Server → Simulation → People → Content | Телосложение | Производное от роста и веса, не def | | Тело и навыки | `SkillDef.bodyLimits` зажимают навык; тело бросается первым | | Влияние характеристик | Никакого; только просмотр | -| Навыки в `core` | Школьные предметы + физические | +| Навыки в `core` | Предметы, языки, общение, физические, рабочие | +| Выдача навыков | Не полный каталог: always, родной, предметы года, взрослые лишние, родственные языки | | Черты в `core` | Около десяти | | Нужды в `core` | Сон, голод, туалет, общение | | Нужды | Машинерия есть, скорость убывания в `core` — ноль | -| Слои по ролям | Одинаковые у всех; родителей не урезаем | +| Слои по ролям | Одинаковые виды данных; ключи навыков зависят от роли и возраста | | Набор имён | Один на школу, выбор в create, в `core` славянский; прочие — моды | +| Родной язык | Один из `nativeLanguages` набора, выбор в create; остальные языки списка — часто низкий навык | | Падежи | Правило по умолчанию (код), явная таблица как исключение (данные) | | Имена и язык UI | Независимы | | Библиотека | `HSchool.People`: зависит от Content, не знает Arch и ASP.NET | -| Детерминизм | Сид в сейве, свой сид на семью | +| Детерминизм | Сид в сейве, свой сид на семью; родной язык — часть входа | | Просмотр | Панель в оболочке менеджера, нижний ряд; не отдельный экран | | Список | Фильтры, сортировки, пейджинг; в строке — только лёгкие поля | | Транспорт списка | HTTP по опубликованному снимку ростера | diff --git a/docs/design/projects.md b/docs/design/projects.md index d6a5df5..79dbe0d 100644 --- a/docs/design/projects.md +++ b/docs/design/projects.md @@ -23,7 +23,7 @@ Client — своя сторона Protocol (TS) + HTTP | Проект | Да | Нет | | --- | --- | --- | | **HSchool.Content** | Типы def, JSONC-загрузчик, наследование, патчи, слияние локалей, граф карты, валидация связности | Arch, часы, HTTP, потоки, пути `mods/` с диска хоста | -| **HSchool.People** | Генерация ростера: семьи, классы, тело/навыки/черты из каталога и сида | Arch, ASP.NET, сокеты, `DateTime.Now`, файлы сейва | +| **HSchool.People** | Генерация ростера: семьи, классы, тело/навыки/черты из каталога, сида и родного языка школы | Arch, ASP.NET, сокеты, `DateTime.Now`, файлы сейва | | **HSchool.Schedule** | Раскладка учебного плана в таблицу уроков вокруг закреплённых правок | Arch, ASP.NET, сокеты, `DateTime.Now`, файлы сейва | | **HSchool.Ai** | Маршруты по графу карты, план дня человека, выбор цели и действия, продвижение плана во времени | Arch, ASP.NET, сокеты, `DateTime.Now`, файлы сейва | | **HSchool.Simulation** | `School`, `GameClock`, Arch `World`, тик, применение раскладки к миру, адаптер к `Ai` | Kestrel, сокеты, `Directory.Enumerate`, сейв-файлы | diff --git a/docs/protocol.md b/docs/protocol.md index 06ad9ae..ee529ba 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -80,7 +80,10 @@ total is computed on the server. `nameSets` is the list of placeable name packs (`defName` + label + `nativeLanguages`). Each `nativeLanguages` entry is a skill (`defName` + label). The create dialog picks a name set and a native language; the language list comes from that set (vanilla Slavic: Russian, Belarusian, -Ukrainian). It is independent of the UI language. +Ukrainian). It is independent of the UI language. Everyone in the school is generated with that +native. Other languages of the same set often appear at a low skill — a Russian speaker who +understands Belarusian. Those rolls live on the `NameSetDef` (`relatedLanguageChance` and +neighbours), not on this catalog payload. `subjects` is the list of placeable subjects (`defName`, label, `gradeMin`/`gradeMax`, `hoursPerWeek`, `skills` with shares, and optional `room`). `room` is the RoomDef the lesson @@ -227,6 +230,9 @@ grid fetches `GET .../timetable?classId=` with it. `activity` is the ActionDef name currently in progress, or `null` when idle. `activityLabel` is that def in the request locale. HTTP JSON is additive — no protocol version bump. +`skills` lists only keys the person has, not every `SkillDef` in the catalog. A first-year has +no Chemistry; a related tongue from the name set may sit beside the native at a low value. + ```json { "id": "f0.c0", @@ -329,8 +335,8 @@ those lessons will not happen. Applicants here are the same people as in `saves/{id}.people.json`. A parent keeps the same id on the roster; hiring them sets `isStaff` on that person and does not create a second entity. Generated candidates (`aN.p0`) join the roster only when hired. `skills` on an -applicant are the three strongest, for the management list; the full set is on the person -card. `positions` and `subjects` are the school's catalog, so the hire and assign pickers +applicant are the three strongest, for the management list; the card lists every skill they +have, not the three strongest. `positions` and `subjects` are the school's catalog, so the hire and assign pickers do not need a second request. `GET /api/schools/{id}/people/{personId}` also opens a card for someone who is only in the