Remove off-queue.md and add new design documentation files including README.md, defs.md, near-term.md, projects.md, runtime.md, people.md, staffing.md, and schedule.md to outline the structure and agreements for the game's design phases.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Фаза 18. Присутствие и ходьба
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 16](../04-schedule/16-timetable-in-school.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Человек перестаёт быть записью в расписании и получает **место**. Он приходит утром, идёт
|
||||
коридором в кабинет и уходит после последнего урока. Экрана ещё нет — всё проверяется тестами
|
||||
и логом.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] Новый проект `HSchool.Ai` рядом с `People` и `Schedule`: зависит на `Content`, `People` и
|
||||
`Schedule`, без Arch и ASP.NET. Рядом — `tests/HSchool.Ai.Tests`
|
||||
- [x] `travelMinutes` на `RoomDef` и `TerritoryDef`; в `core` проставлены кабинет 0.5, коридор
|
||||
1.5, лестница 1.5, вестибюль 1, двор 3
|
||||
- [x] Маршрутизация по `MapLayout.Links` — в библиотеке: матрица следующих шагов считается
|
||||
**один раз** при загрузке школы, не на каждом шаге
|
||||
- [x] План дня человека — тоже в библиотеке: во сколько выходить, чтобы успеть, и когда уходить.
|
||||
Часы, компоненты и мир туда не проникают
|
||||
- [x] Место человека — компонент в `World`: узел, остаток пути, минуты до выхода из узла.
|
||||
Человек всегда в узле; рёбер как состояний нет
|
||||
- [x] Состояние «вне школы» — не удаление сущности: человек остаётся в списке и в карточке
|
||||
- [x] Приход и уход: у кого сегодня нет уроков, тот не приходит вовсе. Ученик и учитель — по
|
||||
своим урокам, прочий штат — по дню школы
|
||||
- [x] Запас на дорогу свой у каждого: путь от двора плюс несколько минут из своего потока
|
||||
случайности, с поправкой на черты
|
||||
- [x] Обязанность как место назначения: урок — кабинет из расписания, должность — комната из
|
||||
`RoomDef.works`. Выбора действий пока нет
|
||||
- [x] Движение по тику: остаток минут в узле уменьшается, при нуле человек переходит в следующий
|
||||
узел пути
|
||||
- [x] Стабильный порядок обхода людей — собственный список, а не порядок сущностей в Arch
|
||||
- [x] Адаптер в `HSchool.Simulation`: собирает значения из компонентов, зовёт библиотеку,
|
||||
записывает ответ обратно. Горячий путь — движение — границу не пересекает
|
||||
- [x] Ориентир в `AGENTS.md`, `docs/architecture.md` и `docs/design/01-shell/projects.md` знает про новый
|
||||
проект
|
||||
- [x] Место, путь и назначение едут в файл часов; кого в файле нет, тот расставляется по
|
||||
обязанности
|
||||
- [x] Потолок решений за тик — в `SimulationOptions`, как очередь, а не как отсечка
|
||||
- [x] Предикат «школа пуста»: в здании и во дворе нет никого
|
||||
- [x] Рабочее окно дня — от шести утра до последнего звонка по **каркасу дня**, а не по
|
||||
фактическому расписанию
|
||||
- [x] «Ближайшее шесть утра рабочего дня впереди»: ночь ведёт в то же утро, вечер — в следующее,
|
||||
выходные, праздники и каникулы пропускаются. Поиск ограничен разумным числом дней и
|
||||
честно отвечает «нет такого»
|
||||
- [x] Прыжок часов туда одним шагом: разрешён только при пустой школе и вне рабочего окна,
|
||||
отрабатывает первое сентября и обновление пула за весь пропуск, после себя пишет сейв
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Путь из кабинета 201 в санузел первого этажа идёт через лестницу и коридор, а не напрямую
|
||||
- [x] Сумма `travelMinutes` совпадает с временем, за которое человек реально доходит
|
||||
- [x] В воскресенье и в каникулы школа пуста: все вне школы
|
||||
- [x] Класс без уроков сегодня не приходит, а его учитель с уроками у другого класса — приходит
|
||||
- [x] К началу первого урока ученик находится в своём кабинете
|
||||
- [x] Физкультура после урока в главном корпусе: класс доходит до спортзала, и видно, что
|
||||
перемены на это едва хватает
|
||||
- [x] Тот же сид и та же карта дают то же расположение людей на тот же момент
|
||||
- [x] Сохранение и загрузка посреди перемены не телепортируют людей
|
||||
- [x] Прыжок с субботы попадает в понедельник, 6:00; с трёх ночи вторника — в утро того же
|
||||
вторника; с десяти вечера — в утро среды
|
||||
- [x] Прыжок в учебное время отклоняется. В семь утра рабочего дня, когда школа ещё пуста, —
|
||||
тоже: это уже рабочее окно
|
||||
- [x] У школы без единого учителя рабочий день не пропускается
|
||||
- [x] Прыжок через летние каникулы проводит первое сентября: классы перешли, выпуск состоялся,
|
||||
набор пришёл
|
||||
- [x] Промотанная неделя и прожитая неделя дают одно состояние школы
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- `dotnet test` проходит
|
||||
- Маршруты и план дня проверены без мира: в `HSchool.Ai.Tests` нет Arch
|
||||
- В `HSchool.Ai` нет упоминаний Arch, ASP.NET и `DateTime.Now`; в `HSchool.Simulation` — сокетов
|
||||
|
||||
## Стоп
|
||||
|
||||
Не трогать протокол и клиент. Не заводить нужды, действия и выбор — это фазы 20 и 21.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Фаза 19. Присутствие на экране
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 18](18-presence-walking.md)
|
||||
- [Фаза 17](../04-schedule/17-timetable-screen.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Школа впервые видна живой: в дереве идут числа, на перемене коридор наполняется, к звонку
|
||||
кабинеты сходятся обратно.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] Новое сообщение присутствия, ~2 раза в секунду, только по открытой школе: узлы со
|
||||
счётчиками и люди с их узлом и состоянием
|
||||
- [x] Снимок карты становится **статическим**: люди и текущий урок уезжают в присутствие,
|
||||
структура уходит один раз при открытии. Пересылка на смене слота убирается
|
||||
- [x] `ProtocolCodec.cs`, `protocol.ts` и `docs/protocol.md` правятся тем же коммитом, версия
|
||||
бумпится до 7
|
||||
- [x] Справочник «id → имя» по HTTP: клиент забирает один раз при открытии школы и перечитывает,
|
||||
увидев незнакомый id. Имена в кадр присутствия не кладутся
|
||||
- [x] Дерево: число людей рядом с узлом, живое. Пустой узел остаётся без числа
|
||||
- [x] Панель локации: кто здесь сейчас, списком с именами; урок в комнате берётся из присутствия,
|
||||
а не из снимка
|
||||
- [x] Карточка человека: где он сейчас — узел, «в пути» или «вне школы»
|
||||
- [x] Присутствие приходит по всей школе, выбранный узел фильтрует клиент
|
||||
- [x] Кадр часов несёт разрешение на пропуск; клиент это разрешение **не вычисляет**
|
||||
- [x] Намерение «пропустить» — своё сообщение, как пауза и скорость. Сервер проверяет условия
|
||||
заново: кадр из браузера не доверенный
|
||||
- [x] Кнопка рядом с паузой и скоростями: появляется только когда сервер разрешил, подписана
|
||||
датой, к которой перенесёт
|
||||
- [x] Строки через `t(...)`, обе локали
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Байтовая раскладка присутствия сходится с обеих сторон
|
||||
- [x] Круговой прогон сообщения: сервер → клиент → те же значения
|
||||
- [x] Снимок карты больше не содержит людей и урока
|
||||
- [x] Кадр часов с разрешением на пропуск читается обеими сторонами одинаково
|
||||
- [x] Пропуск, присланный в учебное время, сервер отбрасывает, а не исполняет
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Открыть школу в 8:25 и увидеть, как двор и вестибюль пустеют, а кабинеты наполняются
|
||||
- На перемене коридор — самый людный узел дерева
|
||||
- В каникулы дерево без чисел, а карточки говорят «вне школы»
|
||||
- В пятницу после уроков дождаться, пока школа опустеет, нажать «пропустить» и оказаться в
|
||||
понедельник в 6:00; вечером буднего дня та же кнопка ведёт в завтрашнее утро
|
||||
- `dotnet test`, `npm test` и `npm run build` проходят
|
||||
|
||||
## Стоп
|
||||
|
||||
Не рисовать перемещение анимацией. Не заводить серверный `OpenLocation`. Не добавлять нужды и
|
||||
действия.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Фаза 20. Нужды и действия
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 19](19-presence-screen.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Нужды перестают быть четырьмя неподвижными полосками, а действия — пустым дефом. Появляется то,
|
||||
из чего фаза 21 будет собирать решения.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] `ActionDef` получает поля: комната, вещь, длительность, восполняемая нужда и величина,
|
||||
роли, вес досуга
|
||||
- [x] Действия в `core`: поесть в столовой, санузел, отдохнуть на перемене, пообщаться,
|
||||
прогуляться по коридору и по двору
|
||||
- [x] Деф правил поведения — как `StaffingDef` у штата: пороги нужд, скорость обучения на уроке,
|
||||
разброс запаса на дорогу, порог переключения решения
|
||||
- [x] Декей нужд включается в `core`. Сон восстанавливается вне школы, а не действием
|
||||
- [x] Действие занимает вещь на время: за один стол не садятся вдвоём
|
||||
- [x] Выполнение действия: начало, отсчёт минут, восполнение нужды по завершении. Правила — в
|
||||
`HSchool.Ai`, компоненты и мир — в `HSchool.Simulation`
|
||||
- [x] Валидатор дефов ловит действие без комнаты, с неизвестной нуждой и с неизвестной вещью
|
||||
- [x] Карточка человека показывает, что он делает; полоски нужд начинают шевелиться
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Голод падает за игровой час ровно на `decayPerHour`
|
||||
- [x] Обед в столовой поднимает голод на заявленную величину и занимает заявленное время
|
||||
- [x] Столов меньше, чем желающих: лишние не начинают действие, а не садятся сквозь друг друга
|
||||
- [x] Ночь вне школы возвращает сон к максимуму
|
||||
- [x] Действие с неизвестной нуждой роняет загрузку каталога с внятной ошибкой
|
||||
- [x] Те же входы дают те же значения нужд на тот же момент
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- `dotnet test` и `npm test` проходят
|
||||
- В карточке за игровой день видно, как нужды опускаются, а после столовой — поднимаются
|
||||
|
||||
## Стоп
|
||||
|
||||
Не подключать выбор действия — люди пока ходят только по обязанности. Не трогать оценки и
|
||||
успеваемость.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Фаза 21. Выбор действия
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 20](20-needs-actions.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Последний кусок среза: обязанность перестаёт быть приказом. Ученик с критической нуждой уходит с
|
||||
урока и возвращается, и это видно в кабинете и в его карточке.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] Цели, веса и планирование — целиком в `HSchool.Ai`: на вход значения, на выход решение.
|
||||
В `HSchool.Simulation` — только сбор входов и запись ответа
|
||||
- [x] Цели и их вес: обязанность — постоянный высокий, нужда — тем больше, чем ближе к нулю,
|
||||
досуг — низкий и только при отсутствии обязанности
|
||||
- [x] Побеждает наибольший вес. Уход с урока получается из сравнения, а не из отдельного правила
|
||||
- [x] Планирование «дойти → сделать»: цель выбирает действие, планировщик достраивает дорогу до
|
||||
подходящей комнаты
|
||||
- [x] Начатое доводится до конца: переключение только при заметном перевесе новой цели
|
||||
- [x] Решения по событиям — звонок, конец действия, приход в назначенный узел, пересечение
|
||||
нуждой порога, — а не каждый тик
|
||||
- [x] Очередь решений с потолком за тик: отложенное принимается следующим тиком, а не пропадает
|
||||
- [x] Возвращение к обязанности после закрытия нужды, если урок ещё идёт
|
||||
- [x] Навык растёт на уроке: от предмета, с поправкой на черты и на состояние нужд
|
||||
- [x] Опоздание и отсутствие видны: в панели локации на уроке не весь класс, в карточке написано,
|
||||
где человек
|
||||
- [x] Строки через `t(...)`, обе локали
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Ученик с нулевым «туалетом» уходит с урока, доходит до санузла и возвращается в кабинет
|
||||
- [x] Нужда чуть ниже порога урок не срывает
|
||||
- [x] Две почти равные нужды не заставляют метаться: действие доводится до конца
|
||||
- [x] На перемене выбирается досуг, на уроке — нет
|
||||
- [x] Навык после учебного дня вырос, у голодного — меньше
|
||||
- [x] Потолок решений за тик не теряет решения, а сдвигает их
|
||||
- [x] Тот же сид и те же действия игрока дают ту же школу через игровую неделю
|
||||
- [x] Разбор решения таблицей входов и выходов, без мира и без хоста
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Прогнать школу на ×4 через учебный день и увидеть осмысленную картину: уроки, перемены с
|
||||
коридором и столовой, редкие отлучки посреди урока
|
||||
- `dotnet test`, `npm test` и `npm run build` проходят
|
||||
|
||||
## Стоп
|
||||
|
||||
Не добавлять оценки, настроение, конфликты и дружбу. Не давать игроку приказы. Не углублять
|
||||
планировщик до полного GOAP.
|
||||
@@ -0,0 +1,24 @@
|
||||
Индекс срезов: [`../README.md`](../README.md).
|
||||
|
||||
## Срез 5. Жизнь школы
|
||||
|
||||
Дизайн: [`../design/ai.md`](../../design/05-ai/ai.md).
|
||||
|
||||
Люди начинают ходить и решать. Присутствие перестаёт вычисляться из расписания и становится
|
||||
состоянием: человек приходит утром, идёт коридором, может уйти с урока в туалет и вернуться.
|
||||
|
||||
Срез идёт **двумя этапами**, и между ними можно остановиться — школа останется целостной.
|
||||
|
||||
**Этап A — присутствие.** Люди ходят по обязанности; выбора у них ещё нет.
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [18. Присутствие и ходьба](18-presence-walking.md) | ✅ | `HSchool.Ai`, место человека, маршруты, приход и уход |
|
||||
| [19. Присутствие на экране](19-presence-screen.md) | ✅ | Своё сообщение ~2 Гц, числа в дереве, статический снимок карты, пропуск пустого времени |
|
||||
|
||||
**Этап B — поведение.** Появляются нужды, действия и выбор между ними и обязанностью.
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [20. Нужды и действия](20-needs-actions.md) | ✅ | `ActionDef` с полями, декей, восполнение |
|
||||
| [21. Выбор действия](21-decisions.md) | ✅ | Цели и веса, «дойти → сделать», уход с урока, рост навыка |
|
||||
@@ -0,0 +1,42 @@
|
||||
# Журнал ревью
|
||||
|
||||
Сводка: [`../reviewed.md`](../reviewed.md). Индекс среза: [`README.md`](README.md).
|
||||
|
||||
## Срез 5. Жизнь школы
|
||||
|
||||
- **Фазы:** 18–21
|
||||
- **Проверен на:** `cbe739a`, 2026-08-20
|
||||
- **Пути:** `src/HSchool.Ai`, `src/HSchool.Simulation/{PresenceSystem,ActivitySystem,LessonLearningSystem,School}.cs`,
|
||||
`src/HSchool.Protocol` (кадр `Presence`, пропуск в кадре часов),
|
||||
`src/HSchool.Server/Game/PresenceFrame.cs`, `src/HSchool.Client/src/ui/gameScreen.ts`,
|
||||
`src/HSchool.Server/mods/core/defs/{actions,behavior,needs}`, `tests/HSchool.Ai.Tests`,
|
||||
`tests/HSchool.Simulation.Tests/{PresenceTests,DecisionTests,ActivityTests,NeedDecayTests,LunchTests}.cs`,
|
||||
`tests/HSchool.AppHost.Tests/GameSocketTests.cs`
|
||||
- **Итог:** все 32 теста из списков фаз на месте; дописаны 2 теста явки; `SetTimetable` сбрасывает
|
||||
планы дня. Голод закрыт данными. AppHost после правки не гонялся — Aspire держал DLL.
|
||||
|
||||
Что подтверждено:
|
||||
|
||||
- Ходьба: 13 тестов списка фазы 18 (маршрут, `travelMinutes`, воскресенье/каникулы, звонок,
|
||||
детерминизм, пропуск пустого времени, лето, промотанная неделя).
|
||||
- Присутствие: раскладка с обеих сторон, круговой прогон, люди не в снимке карты, пропуск в
|
||||
учебное время отбрасывается. На паузе кадры **идут** (occupancy + подписи урока); людей в них
|
||||
может не быть.
|
||||
- Нужды: декей, обед, стулья, ночь вне школы, неизвестная нужда, детерминизм.
|
||||
`Hunger` восстанавливается вне школы, в столовой 112 стульев, обед — смена по параллелям.
|
||||
`SleepAndHunger_ReturnToMaxOffCampus`, `AfterASchoolDay_NobodyIsLeftStarving`.
|
||||
- Решения: восемь тестов фазы 21, в том числе туалет с урока и возврат, потолок отложенных,
|
||||
детерминизм за неделю. `HSchool.Ai` без Arch/ASP.NET/`DateTime.Now`.
|
||||
|
||||
Дописано:
|
||||
|
||||
- `HireAndAssignMath_DuringLessonThree_PutsSomeoneOnCampus`
|
||||
- `AssigningMath_AfterDayPlansWereBuilt_PutsSomeoneOnCampus`
|
||||
|
||||
Исправлено:
|
||||
|
||||
- `School.SetTimetable` обнуляет `PlanDay`. Иначе после назначения предмета без смены численности
|
||||
`EnsurePlans` считает планы актуальными, `AppearAt` остаётся `null`, кампус пуст. Найм это
|
||||
маскировал (численность растёт).
|
||||
- `OpeningASchoolDuringAMathLesson_...` после снятия паузы сразу ждал людей и съедал бюджет на
|
||||
паузные кадры. Теперь ждёт `clock.Running`, потом людей.
|
||||
Reference in New Issue
Block a user