Петля как ядро

Петля — центральная метафора проекта, не просто фича. Объясняет, что такое петля в нарративе, как она реализована в коде, и почему структура (loop, day) пронизывает всю систему.

Mother of Learning — игра про прогрессию через циклы. Петля — это период игрового времени с фиксированным началом и условием сброса: мир возвращается к исходному состоянию, но персонажи сохраняют память, уровни и навыки. Нарративная механика новеллы Домогая стала архитектурной опорой инструмента.


Петля в нарративе

Группа проживает один цикл «реального» времени мира (в текущей кампании — 30 дней, хотя длина настраивается). В конце петли DM объявляет сброс: NPC забывают, данжи перезаполняются, некоторые последствия откатываются. Игроки несут с собой только то, что пережило сброс: уровни, абилки, часть золота, ключевые предметы. Пережить петлю значит стать лучше — это и есть прогрессия в progression fantasy.

Петля в коде

До миграции 012 петля жила в отдельной таблице loops. После — петля стала нодой типа loop в общем графе (см. node-graph.md).

Поля nodes.fields для петли:

ПолеТипСмысл
numberintпорядковый номер петли: 1, 2, 3…
status'past' / 'current' / 'future'активна ли петля
length_daysint, дефолт 30длина в днях (миграция 032)

Сессии — ноды типа session, связанные с петлей рёбром contains (loop → session). Состав пачки — рёбра participated_in (session → character, миграция 032).

Все транзакции несут (loop_number, day_in_loop) как временно́й якорь — это позволяет фильтровать ленту бухгалтерии по петле, строить прогрессбар и восстанавливать состояние «на конец дня N петли M».

Frontier — фронтир текущей петли

Прогрессбар петли (LoopProgressBar) рендерит ось от Day 1 до loop.length_days. Каждая сессия с заполненными day_from/day_to ложится сегментом на соответствующую дорожку. Если сессии перекрываются по дням, алгоритм assignLanes (greedy) распределяет их по дополнительным рядам.

Для status='current' на баре рисуется фронтир — пунктирная вертикальная линия после max(day_to) всех сессий с подписью «Дошли до дня N». Это ответ на вопрос DM: «где сейчас группа в текущей петле?»

Сессии без day_from/day_to выводятся отдельным рядом пилюль ниже бара.

Сессия как диапазон дней

Сессия хранит day_from и day_to — это диапазон игровых дней, которые охватывала встреча. Один реальный вечер может охватывать несколько игровых дней (или меньше одного). Все транзакции, созданные в рамках сессии, ссылаются на session_id, но их day_in_loop указывается явно — потому что в рамках одной сессии разные события могут происходить в разные дни.

Связь с временно́й моделью

В проде сейчас: (loop_number, day_in_loop) — целые числа. Это грубая, но работающая модель.

В целевой архитектуре (HANDOFF): (loop_id, at_tick), где at_tick — целое от точки отсчёта кампании. loop_id — UUID, не порядковый номер. Это нужно для точной временно́й сортировки событий внутри дня и для ветвления петель (branch_id).

time-as-resource.md, roadmap/tick-time-model.md

Прошлые петли read-only

Петли с status='past' доступны только для чтения. Лента событий прошлых петель — хроника кампании; её нельзя редактировать (только через DM-инструменты коррекции). Это база для future «time-travel UI» — просмотра состояния мира на конкретный момент прошлой петли.


persistence-scope.md — что именно переживает сброс петли. → features/loops-and-sessions/README.md — как создавать петли и сессии в UI.