Implement civilization flow mechanics and profiling for resource allocation

- Added `civilization_flow.gd` to manage continuous expected flows and resource allocation within civilizations.
- Introduced `allocate_profiled` and `whole_quotas` functions in `quantity_math.gd` for precise stock allocation based on float shares.
- Enhanced `credit` logic in `object_ledger.gd` to handle production remainders more effectively.
- Updated `append_batch` in `object_batches.gd` to prevent batch creation for invalid IDs.
- Introduced `ratio_approx` function in `exact.gd` for better handling of float profiles.
- Added a benchmark script `benchmark_civilization_flows.gd` to evaluate the performance of civilization flow mechanics.
- Refactored various functions to improve clarity and efficiency in handling resource flows and allocations.
This commit is contained in:
Kirill
2026-10-07 22:51:55 +03:00
parent 6ee66a627d
commit 3fcc7211ce
41 changed files with 247959 additions and 817 deletions
+42 -17
View File
@@ -122,7 +122,41 @@ godot --headless --path Owniverse.GI --script res://tests/test_time.gd
## Согласованные правила эволюции
Сохраняются постепенные интервальные окна GI: начало преобразования — через `lifespan`, длительность окна — `lifespan / 40` при `lifespan > 10`, иначе `lifespan`.
Сохраняются постепенные интервальные окна GI: срок жизни делится на 40 возрастных групп; начало преобразования — через `lifespan`, длительность окна — `lifespan / 40` при `lifespan > 10`, иначе `lifespan`.
На скоростях 4–6 узкие звёздные партии могут объединяться по границе полного
цикла смерти шириной 200/2000/20000 игровых лет. Прежнее окно шире цикла
сохраняется: долгоживущие звёзды не дробятся. Из существующих партий сливаются
только две или более одного типа, чей оставшийся переход полностью попадает
в общий цикл; широкие и пересекающие границу партии сохраняются.
`test_batch_boundaries` проверяет объединение, точные большие количества и
остатки, однократное изъятие, сериализацию, сохранение широких окон,
распределённые рождения и интеграл производства.
`benchmark_large_star_cohorts.gd` создаёт отдельные большие диагностические
сохранения со старой и новой звёздной сеткой при одинаковых количествах и
входных интервалах рождения. Переключатель `batches.cycle_stars` используется
только для сравнительного замера, в игре он включён. Парные прогоны меняют
порядок моделей и сбрасывают исходное состояние перед каждым запуском:
```sh
godot --headless --path Owniverse.GI --script res://tests/benchmark_large_star_cohorts.gd -- cycles=50 repeats=2
```
Сохранения и полные профили записываются в `tests/artifacts/large_star_cohorts_*`;
сохранение игрока не затрагивается. `generate_only` проверяет запись/чтение и
исходное равенство физических количеств без запуска замеров.
`benchmark_many_objects.gd` создаёт новую диагностическую вселенную со всеми
типами объектов и цивилизаций и 4800 синтетическими звёздными партиями,
попадающими группами в общие циклы. Это отдельный стресс-сценарий большого
числа партий; старый и новый расчёты используют одинаковый исходный состав.
```sh
godot --headless --path Owniverse.GI --script res://tests/benchmark_many_objects.gd -- cycles=40 repeats=2
```
Файлы сценария: `tests/artifacts/many_objects_fragmented_stars_*`.
Вероятностные исходы используют накопление дробного остатка GI, без случайного округления. Этот же подход выбран для будущего создания планет. Шансы планет записаны долями (`0.01` = 1%), а альтернативные исходы звёзд — процентами (`%0.1` = 0.1%). Парсер планет сохраняет дроби и поддерживает один элемент без `&`.
@@ -209,8 +243,7 @@ godot --path Owniverse.GI --script res://tests/benchmark_civilizations.gd -- ui
Stage вызывает `evolute_frame`: транзакция получает бюджет 40 мс и уступает
следующему кадру внутри создания партий и обработки стадий. Расчёт остаётся
на главном потоке, состояние публикуется только после полного завершения.
Длительность одной транзакции ограничена обычным шагом 1/60 секунды выбранной
скорости. Запрошенное время хранится отдельно, поэтому отставание не превращается
Одна транзакция обрабатывает 0,2 реальной секунды на любой скорости. Запрошенное время хранится отдельно, поэтому отставание не превращается
в один всё более тяжёлый шаг. При предельной нагрузке время симуляции может
отставать от запрошенного; это не ограничение FPS интерфейса и не удаление событий.
@@ -259,20 +292,12 @@ Stage вызывает `evolute_frame`: транзакция получает б
1.057. Замер включает сокращение накопленного отставания сохранения;
это результат конкретного сценария на Mac, а не гарантия для Android.
Адаптивный шаг на скоростях 4–6 выбирает 0.1, 0.2 или 0.5 реальной секунды.
Долг больше двух шагов повышает ступень, меньше половины шага понижает её.
Шаг ограничен доступным запрошенным временем. Скорости 1–3 сохраняют 1/60;
смена скорости сбрасывает ступень. Возобновляемая транзакция сохраняет точную
границу из checkpoint, адаптация применяется к следующей транзакции.
Бюджет кадра остаётся 40 мс; ширина временных партий не меняется.
`test_frame_evolution` проверяет ступени, гистерезис, сохранение долга,
переключение скорости, возобновление и совпадение с прямым расчётом того же шага.
На свежей диагностической копии сохранения с долгом 407.79 млн лет:
600 кадров реального UI на M4 Pro дали 18.05 FPS (p95 92.91 мс,
максимум 122.45 мс), поступило 3.335 млн лет, обработано 6.480 млн:
пропускная способность 1.943 вместо 0.787 при фиксированном шаге 0.1.
Разбиение времени влияет на дискретные производство и глобальные параметры;
адаптивные шаги не обещают совпадения результата с последовательностью 0.1.
Полный шаг фиксирован: 0,2 реальной секунды на всех скоростях, пять циклов
на секунду запрошенного времени. Неполный интервал накапливается. При отставании
шаг сохраняется, долг не отбрасывается. Возобновляемая транзакция сохраняет
границу из checkpoint. Бюджет кадра остаётся 40 мс. `test_frame_evolution`
проверяет расписание всех шести скоростей, сохранение долга и пять циклов
на одну секунду.
Дипломатический drift использует шесть взвешенных вкладов вместо матрицы
пар этик: вес = сумма вкладов + 195 × свой вклад − противоположный вклад.