Refactor civilization flow mechanics: enhance commit and colonization logic, add tests for flow application and resource allocation, and optimize performance metrics.
This commit is contained in:
@@ -139,6 +139,10 @@ HP деградирует в RP. У эонов возможен откат к п
|
|||||||
|
|
||||||
Колонизация агрегирует запросы по стадии назначения (на две стадии ниже отправителя), ограничивает их общим запасом GG, AB, RP и HP и заменяет ровно выделенное число планет. Целые колонии сохраняют владельца целевой планеты; состав получает дрейф 960/4/9. Исходное население не расходуется.
|
Колонизация агрегирует запросы по стадии назначения (на две стадии ниже отправителя), ограничивает их общим запасом GG, AB, RP и HP и заменяет ровно выделенное число планет. Целые колонии сохраняют владельца целевой планеты; состав получает дрейф 960/4/9. Исходное население не расходуется.
|
||||||
|
|
||||||
|
Применение потоков сначала строит таблицу исходных владельцев. Для каждой исходной стадии готовые целые квоты распределяются по строкам владельцев; последняя строка получает точный остаток. Стадии с единственным свободным запасом применяют готовые квоты напрямую. Поступления объединяются по стадии и владельцу; физическая выдача и статистика создания выполняются один раз на получателя. Ct всегда остаётся свободной от привязок.
|
||||||
|
|
||||||
|
При колонизации планеты сначала списываются по типам и владельцам, затем суммарное списание каждого владельца распределяется между стадиями колоний. Каждая стадия получает одну суммарную выдачу. Общие целые квоты, число списанных планет и количество колоний сохраняются точно. Из-за объединения распределений единичные остатки между владельцами могут отличаться от прежнего последовательного порядка; вероятности переходов и формулы этик не меняются.
|
||||||
|
|
||||||
Космические стадии C2.0–C4.4 свободны от планетных привязок. Общие бюджеты звёздных семейств и структур учитывают уже занятые резервы. Неподдерживаемый промежуточный переход блокируется в операторе; конечные положительные запросы делят свободную ёмкость одновременно. Отклонённые количества возвращаются к источнику. Освободившаяся при переходах ёмкость доступна следующему шагу. Если внешние изменения уменьшили ёмкость ниже существующего населения, избыток последовательно деградирует с приоритетом старших стадий. При возвращении в планетные стадии используются реальные карликовые звёзды, при отсутствии хозяина население остаётся свободным.
|
Космические стадии C2.0–C4.4 свободны от планетных привязок. Общие бюджеты звёздных семейств и структур учитывают уже занятые резервы. Неподдерживаемый промежуточный переход блокируется в операторе; конечные положительные запросы делят свободную ёмкость одновременно. Отклонённые количества возвращаются к источнику. Освободившаяся при переходах ёмкость доступна следующему шагу. Если внешние изменения уменьшили ёмкость ниже существующего населения, избыток последовательно деградирует с приоритетом старших стадий. При возвращении в планетные стадии используются реальные карликовые звёзды, при отсутствии хозяина население остаётся свободным.
|
||||||
|
|
||||||
Порядок полного шага: производство за интервал → непрерывные потоки существующих цивилизаций → поколения звёзд и биологической жизни и бласты → итоговые ограничения среды → тренды. Возникшие из C0.1 цивилизации C0.2 получают равномерный профиль, смешанный с существующим населением, и начинают непрерывную эволюцию со следующего шага. Разные размеры полного шага могут отличаться из-за этого порядка, ограничений среды и нелинейных эффектов; чистая непрерывная цепочка без ограничений согласована при разделении интервала.
|
Порядок полного шага: производство за интервал → непрерывные потоки существующих цивилизаций → поколения звёзд и биологической жизни и бласты → итоговые ограничения среды → тренды. Возникшие из C0.1 цивилизации C0.2 получают равномерный профиль, смешанный с существующим населением, и начинают непрерывную эволюцию со следующего шага. Разные размеры полного шага могут отличаться из-за этого порядка, ограничений среды и нелинейных эффектов; чистая непрерывная цепочка без ограничений согласована при разделении интервала.
|
||||||
|
|||||||
@@ -238,6 +238,12 @@ godot --path Owniverse.GI --script res://tests/benchmark_civilizations.gd -- ui
|
|||||||
|
|
||||||
## Расчёт между кадрами
|
## Расчёт между кадрами
|
||||||
|
|
||||||
|
`test_flow_commit.gd` проверяет консолидированное применение переходов и колонизации: точные квоты получателей, сохранение количества у каждого владельца, профили этик, статистику создания и отсутствие привязок у Ct. Проверки используют несколько владельцев и численность 103, 10^40 + 103 и 10^400 + 103.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
godot --headless --path Owniverse.GI --script res://tests/test_flow_commit.gd
|
||||||
|
```
|
||||||
|
|
||||||
`godot --headless --path Owniverse.GI --script res://tests/test_frame_evolution.gd`
|
`godot --headless --path Owniverse.GI --script res://tests/test_frame_evolution.gd`
|
||||||
|
|
||||||
Stage вызывает `evolute_frame`: транзакция получает бюджет 40 мс и уступает
|
Stage вызывает `evolute_frame`: транзакция получает бюджет 40 мс и уступает
|
||||||
|
|||||||
@@ -379,3 +379,36 @@ godot --headless --path . --script res://tests/benchmark_large_star_cohorts.gd -
|
|||||||
```sh
|
```sh
|
||||||
godot --headless --path . --script res://tests/benchmark_many_objects.gd -- cycles=40 repeats=2
|
godot --headless --path . --script res://tests/benchmark_many_objects.gd -- cycles=40 repeats=2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Консолидация применения потоков и колонизации — 2026-10-08
|
||||||
|
|
||||||
|
Первый этап: исходное население распределяется по строкам владельцев одной таблицы переходов. Свободные стадии применяют готовые целые квоты напрямую. При колонизации списания планет объединяются по владельцам; каждая стадия колоний получает одну суммарную выдачу. Общие целые количества и статистика сохранены. Изменён порядок распределения единичных остатков между владельцами; полного совпадения состояния с прежним порядком округления не заявляется. Ct остаётся свободной от привязок.
|
||||||
|
|
||||||
|
До и после загружались одни и те же диагностические файлы с теми же количествами и партиями. Скорость 6, полный интервал 0,2 секунды (20 000 игровых лет), CPU-профилирование включено, UI отсутствует. По два прогона из исходного состояния, каждый по 20 циклов: до → после → после → до. На каждую модель и сохранение обработано 800 000 игровых лет. Валидация начальных и конечных состояний прошла; SHA-256 входных файлов до и после совпали. Сохранение игрока не использовалось.
|
||||||
|
|
||||||
|
| Сохранение | До, мс | После, мс | Сокращение времени | Полных циклов/с после |
|
||||||
|
|---|---:|---:|---:|---:|
|
||||||
|
| Все объекты | 385,263 | 377,222 | 2,09% | 2,651 |
|
||||||
|
| Много объектов и партий | 506,888 | 443,303 | 12,54% | 2,256 |
|
||||||
|
|
||||||
|
Для тяжёлого сохранения:
|
||||||
|
|
||||||
|
| Участок | До, мс/цикл | После, мс/цикл |
|
||||||
|
|---|---:|---:|
|
||||||
|
| Применение переходов | 113,011 | 91,591 |
|
||||||
|
| Колонизация | 53,487 | 11,520 |
|
||||||
|
| Подготовка потоков | 114,808 | 114,742 |
|
||||||
|
| Поколения звёзд и жизни | 116,085 | 115,999 |
|
||||||
|
|
||||||
|
Первый этап сокращает полный тяжёлый цикл на 12.54%, но цель пяти циклов в секунду не достигнута. До 200 мс нужно ещё примерно 2.22-кратное ускорение. Следующие крупные затраты — подготовка цивилизационных потоков, поколения и оставшееся применение переходов.
|
||||||
|
|
||||||
|
Проверки: целочисленные квоты и владельцы, включая 10^400 + 103 — 1068; цивилизационные потоки — 1895; состояние цивилизаций — 70; кадровый планировщик — 38. Всего 3071 проверка без ошибок. Проверены сохранение населения каждого владельца при планетных переходах, точные поступления по стадиям, замена планет колониями, статистика и Ct.
|
||||||
|
|
||||||
|
Полные профили, отдельные прогоны и контрольные суммы: `flow_commit_step1_results.json`. Базовая версия: `413f2be9044090c878c2909dd9d0646f77513a5f`.
|
||||||
|
|
||||||
|
Для замера текущей версии на тех же входных файлах:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
godot --headless --path . --script res://tests/benchmark_civilization_flows.gd -- res://tests/artifacts/all_objects_speed6.adventure.json 0.2 profile cycles=20
|
||||||
|
godot --headless --path . --script res://tests/benchmark_civilization_flows.gd -- res://tests/artifacts/many_objects_fragmented_stars_cycle.adventure.json 0.2 profile cycles=20
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,763 @@
|
|||||||
|
{
|
||||||
|
"delta_seconds": 0.2,
|
||||||
|
"input_sha256": {
|
||||||
|
"all_objects_speed6": "44bee3b3753fa51615f766d8f800a10cc2b70c8e7fb4ea12b6e18da7f07a7d67",
|
||||||
|
"many_objects_fragmented_stars_cycle": "1e95ef398923f26b912a305c84f9b3eb502d24cb14e8ae687a4becccf047324a"
|
||||||
|
},
|
||||||
|
"order": "before-after-after-before",
|
||||||
|
"profile_enabled": true,
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 407.447,
|
||||||
|
"mean_ms": 382.1863,
|
||||||
|
"min_ms": 338.878,
|
||||||
|
"model": "before",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
23607,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
119827,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
100257,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
167710,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
1031564,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2148765,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
60291,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
665230,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
338749,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
187536,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
520136,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2614358,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
112213,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
118460,
|
||||||
|
3016
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
478063,
|
||||||
|
360
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
537724,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
349106,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 1,
|
||||||
|
"save": "all_objects_speed6",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 406.895,
|
||||||
|
"mean_ms": 376.23395,
|
||||||
|
"min_ms": 324.14,
|
||||||
|
"model": "after",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
23735,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
120538,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
50071,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
169132,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
892018,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2165803,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
60679,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
670541,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
340289,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
188663,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
534195,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2649493,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
113482,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
118902,
|
||||||
|
3016
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
489793,
|
||||||
|
360
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
548119,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
350991,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 1,
|
||||||
|
"save": "all_objects_speed6",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 413.636,
|
||||||
|
"mean_ms": 378.2097,
|
||||||
|
"min_ms": 326.044,
|
||||||
|
"model": "after",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
23901,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
121116,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
50174,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
170232,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
899208,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2173515,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
61133,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
672190,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
341889,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
190021,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
537089,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2668071,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
113520,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
120186,
|
||||||
|
3016
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
491086,
|
||||||
|
360
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
549548,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
352056,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 2,
|
||||||
|
"save": "all_objects_speed6",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 410.851,
|
||||||
|
"mean_ms": 388.3392,
|
||||||
|
"min_ms": 346.936,
|
||||||
|
"model": "before",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
23780,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
121258,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
101386,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
171098,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
1048869,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2182234,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
61215,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
676192,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
343586,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
191018,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
528628,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2654320,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
113911,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
120518,
|
||||||
|
3016
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
485368,
|
||||||
|
360
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
550201,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
354035,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 2,
|
||||||
|
"save": "all_objects_speed6",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 540.275,
|
||||||
|
"mean_ms": 504.8664,
|
||||||
|
"min_ms": 445.592,
|
||||||
|
"model": "before",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
17920,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
136151,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
1064307,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
195983,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
2251097,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2284423,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
62124,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
678656,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
288140,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
77749,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
795116,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2321187,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
140958,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
54878,
|
||||||
|
1490
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
746203,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
744868,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
355994,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 1,
|
||||||
|
"save": "many_objects_fragmented_stars_cycle",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 462.134,
|
||||||
|
"mean_ms": 441.9819,
|
||||||
|
"min_ms": 389.761,
|
||||||
|
"model": "after",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
17865,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
137136,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
229748,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
196611,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
1828223,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2286989,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
62177,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
678566,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
288805,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
78203,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
805143,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2312257,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
141951,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
55057,
|
||||||
|
1490
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
746690,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
749636,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
355174,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 1,
|
||||||
|
"save": "many_objects_fragmented_stars_cycle",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 467.425,
|
||||||
|
"mean_ms": 444.6246,
|
||||||
|
"min_ms": 389.196,
|
||||||
|
"model": "after",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
18039,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
137286,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
231059,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
197868,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
1835420,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2302705,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
62638,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
680863,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
289856,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
78541,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
808144,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2327718,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
142049,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
55184,
|
||||||
|
1490
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
752516,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
752648,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
358218,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 2,
|
||||||
|
"save": "many_objects_fragmented_stars_cycle",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cycles": 20,
|
||||||
|
"max_ms": 532.382,
|
||||||
|
"mean_ms": 508.9093,
|
||||||
|
"min_ms": 451.042,
|
||||||
|
"model": "before",
|
||||||
|
"profile": {
|
||||||
|
"assign_homes": [
|
||||||
|
18208,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"civilization_flow_capacity": [
|
||||||
|
137370,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_colonies": [
|
||||||
|
1075170,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_finish": [
|
||||||
|
198272,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_ledger": [
|
||||||
|
2269355,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_flow_plan": [
|
||||||
|
2307886,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_build": [
|
||||||
|
62940,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"civilization_operator_solve": [
|
||||||
|
683671,
|
||||||
|
860
|
||||||
|
],
|
||||||
|
"enforce_capacity": [
|
||||||
|
291171,
|
||||||
|
60
|
||||||
|
],
|
||||||
|
"generation_products": [
|
||||||
|
78498,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"generation_withdrawal": [
|
||||||
|
807187,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"generations": [
|
||||||
|
2322215,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"initialize": [
|
||||||
|
143015,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"newborn_batches": [
|
||||||
|
55362,
|
||||||
|
1490
|
||||||
|
],
|
||||||
|
"physical_amounts_build": [
|
||||||
|
749843,
|
||||||
|
300
|
||||||
|
],
|
||||||
|
"production": [
|
||||||
|
753597,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"trends": [
|
||||||
|
360333,
|
||||||
|
20
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"run": 2,
|
||||||
|
"save": "many_objects_fragmented_stars_cycle",
|
||||||
|
"validation": "",
|
||||||
|
"years": 400000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"speed": 6,
|
||||||
|
"reference_commit": "413f2be9044090c878c2909dd9d0646f77513a5f",
|
||||||
|
"reference_script_sha256": "b2a04cc50ad1e77b45762264846cb546b013b09f4c204ba22e6472a38728e5b7",
|
||||||
|
"candidate_script_sha256": "cbc65eaf4ab0e67fb9d6d5d7ad11757bdeb5f0b1e0ffb2f2631bfe3dcd9e962e",
|
||||||
|
"summary": {
|
||||||
|
"all_objects_speed6": {
|
||||||
|
"before": {
|
||||||
|
"mean_ms": 385.26275,
|
||||||
|
"cycles_per_second": 2.5956311634073113,
|
||||||
|
"profile_ms": {
|
||||||
|
"assign_homes": 1.184675,
|
||||||
|
"civilization_flow_capacity": 6.027125,
|
||||||
|
"civilization_flow_colonies": 5.041075,
|
||||||
|
"civilization_flow_finish": 8.4702,
|
||||||
|
"civilization_flow_ledger": 52.010825,
|
||||||
|
"civilization_flow_plan": 108.27497500000001,
|
||||||
|
"civilization_operator_build": 3.03765,
|
||||||
|
"civilization_operator_solve": 33.53555,
|
||||||
|
"enforce_capacity": 17.058375,
|
||||||
|
"generation_products": 9.46385,
|
||||||
|
"generation_withdrawal": 26.219099999999997,
|
||||||
|
"generations": 131.71695000000003,
|
||||||
|
"initialize": 5.6531,
|
||||||
|
"newborn_batches": 5.97445,
|
||||||
|
"physical_amounts_build": 24.085775,
|
||||||
|
"production": 27.198125,
|
||||||
|
"trends": 17.578525000000003
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"mean_ms": 377.22182499999997,
|
||||||
|
"cycles_per_second": 2.6509600816442687,
|
||||||
|
"profile_ms": {
|
||||||
|
"assign_homes": 1.1909,
|
||||||
|
"civilization_flow_capacity": 6.04135,
|
||||||
|
"civilization_flow_colonies": 2.506125,
|
||||||
|
"civilization_flow_finish": 8.4841,
|
||||||
|
"civilization_flow_ledger": 44.78065,
|
||||||
|
"civilization_flow_plan": 108.48295,
|
||||||
|
"civilization_operator_build": 3.0453,
|
||||||
|
"civilization_operator_solve": 33.568275,
|
||||||
|
"enforce_capacity": 17.05445,
|
||||||
|
"generation_products": 9.4671,
|
||||||
|
"generation_withdrawal": 26.7821,
|
||||||
|
"generations": 132.9391,
|
||||||
|
"initialize": 5.675050000000001,
|
||||||
|
"newborn_batches": 5.9772,
|
||||||
|
"physical_amounts_build": 24.521974999999998,
|
||||||
|
"production": 27.441675,
|
||||||
|
"trends": 17.576175
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reduction_percent": 2.0871275512621024
|
||||||
|
},
|
||||||
|
"many_objects_fragmented_stars_cycle": {
|
||||||
|
"before": {
|
||||||
|
"mean_ms": 506.88784999999996,
|
||||||
|
"cycles_per_second": 1.9728229824407906,
|
||||||
|
"profile_ms": {
|
||||||
|
"assign_homes": 0.9032,
|
||||||
|
"civilization_flow_capacity": 6.838025,
|
||||||
|
"civilization_flow_colonies": 53.486925,
|
||||||
|
"civilization_flow_finish": 9.856375,
|
||||||
|
"civilization_flow_ledger": 113.0113,
|
||||||
|
"civilization_flow_plan": 114.807725,
|
||||||
|
"civilization_operator_build": 3.1266,
|
||||||
|
"civilization_operator_solve": 34.058175000000006,
|
||||||
|
"enforce_capacity": 14.482775,
|
||||||
|
"generation_products": 3.906175,
|
||||||
|
"generation_withdrawal": 40.057575,
|
||||||
|
"generations": 116.08505000000001,
|
||||||
|
"initialize": 7.099324999999999,
|
||||||
|
"newborn_batches": 2.756,
|
||||||
|
"physical_amounts_build": 37.40115,
|
||||||
|
"production": 37.461625,
|
||||||
|
"trends": 17.908175
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"after": {
|
||||||
|
"mean_ms": 443.30325,
|
||||||
|
"cycles_per_second": 2.255792169355853,
|
||||||
|
"profile_ms": {
|
||||||
|
"assign_homes": 0.8976000000000001,
|
||||||
|
"civilization_flow_capacity": 6.86055,
|
||||||
|
"civilization_flow_colonies": 11.520175,
|
||||||
|
"civilization_flow_finish": 9.861975000000001,
|
||||||
|
"civilization_flow_ledger": 91.591075,
|
||||||
|
"civilization_flow_plan": 114.74235,
|
||||||
|
"civilization_operator_build": 3.120375,
|
||||||
|
"civilization_operator_solve": 33.985724999999995,
|
||||||
|
"enforce_capacity": 14.466524999999999,
|
||||||
|
"generation_products": 3.9186,
|
||||||
|
"generation_withdrawal": 40.332175,
|
||||||
|
"generations": 115.999375,
|
||||||
|
"initialize": 7.1,
|
||||||
|
"newborn_batches": 2.756025,
|
||||||
|
"physical_amounts_build": 37.48015,
|
||||||
|
"production": 37.5571,
|
||||||
|
"trends": 17.834799999999998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reduction_percent": 12.544116020930463
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
extends "res://tests/test_civilization_evolution.gd"
|
||||||
|
|
||||||
|
func run():
|
||||||
|
var rules: Dictionary = root.get_node("Global").CivilizationRules
|
||||||
|
for count in [103, E.of("10000000000000000000000000000000000000103"), E.add(E.of("1e400"), 103)]:
|
||||||
|
var world = fixture()
|
||||||
|
var third: Variant = E.floor_value(E.divide(count, 3))
|
||||||
|
var free: Variant = E.subtract(count, E.multiply(third, 2))
|
||||||
|
world.state.amount["C0.2"] = free
|
||||||
|
world.state.binds.RD = {"C0.2": third}
|
||||||
|
world.state.binds.OD = {"C0.2": third}
|
||||||
|
var counts: Dictionary = {"C0.2": third, "C0.3": third, "HP": free}
|
||||||
|
var profile: Dictionary = {"m": 0.4, "l": 0.2, "w": 0.1, "d": 0.1, "c": 0.1, "b": 0.1}
|
||||||
|
var profiles: Dictionary = {}
|
||||||
|
for id in counts: profiles[id] = profile
|
||||||
|
var physical: Dictionary = world.ledger.physical_amounts(world.state)
|
||||||
|
world.civilization_flow._commit(world.state, physical, {"C0.2": {"counts": counts, "profiles": profiles}}, rules, 100)
|
||||||
|
for id in counts:
|
||||||
|
check(E.eq(world.ledger.physical_amount(world.state, id), counts[id]), "Commit preserves exact destination quota: " + id)
|
||||||
|
for owner in ["RD", "OD"]:
|
||||||
|
var held: Variant = 0
|
||||||
|
for id in counts: held = E.add(held, world.state.binds[owner].get(id, 0))
|
||||||
|
check(E.eq(held, third), "Commit preserves each owner's exact population")
|
||||||
|
for id in ["C0.2", "C0.3"]:
|
||||||
|
for ethic in profile: check(absf(world.state.ethics[id][ethic] - profile[ethic]) < 1e-12, "Commit preserves incoming ethical profile")
|
||||||
|
invariants(world)
|
||||||
|
dispose(world)
|
||||||
|
world = fixture()
|
||||||
|
world.state.binds.RD = {"C4.4": count}
|
||||||
|
var terminal: Dictionary = {"Ct": State.empty_profile()}
|
||||||
|
world.civilization_flow._commit(world.state, world.ledger.physical_amounts(world.state), {"C4.4": {"counts": {"Ct": count}, "profiles": terminal}}, rules, 100)
|
||||||
|
check(E.eq(world.state.amount.Ct, count), "Transcendent population is entirely free")
|
||||||
|
check(E.eq(world.state.binds.RD.get("Ct", 0), 0), "Transcendent population cannot retain a stellar owner")
|
||||||
|
dispose(world)
|
||||||
|
world = fixture()
|
||||||
|
var original_owners: Dictionary = {}
|
||||||
|
for owner in ["RD", "OD", "YD", "WYD"]:
|
||||||
|
world.state.binds[owner] = {}
|
||||||
|
for resource in ["GG", "AB", "RP", "HP"]:
|
||||||
|
world.state.binds[owner][resource] = count
|
||||||
|
original_owners[owner] = E.multiply(count, 4)
|
||||||
|
var colonies: Dictionary = {
|
||||||
|
"C1.4": {"counts": {"C1.4": E.multiply(count, 3)}, "profiles": {"C1.4": profile}},
|
||||||
|
"C1.5": {"counts": {"C1.5": E.multiply(count, 5)}, "profiles": {"C1.5": profile}}
|
||||||
|
}
|
||||||
|
world.civilization_flow._colonize(world.state, colonies, 100, rules)
|
||||||
|
check(E.eq(world.ledger.physical_amount(world.state, "C1.4"), E.multiply(count, 3)), "Colonization credits exact first quota")
|
||||||
|
check(E.eq(world.ledger.physical_amount(world.state, "C1.5"), E.multiply(count, 5)), "Colonization credits exact second quota")
|
||||||
|
check(E.eq(world.state.stats.total_amount["C1.4"], E.multiply(count, 3)), "Consolidated credit preserves creation statistics")
|
||||||
|
check(E.eq(world.state.civilization_stats.colonies, E.multiply(count, 8)), "Colonization statistics equal exact granted total")
|
||||||
|
for owner in original_owners:
|
||||||
|
var held: Variant = 0
|
||||||
|
for id in ["GG", "AB", "RP", "HP", "C1.4", "C1.5"]: held = E.add(held, world.state.binds[owner].get(id, 0))
|
||||||
|
check(E.eq(held, original_owners[owner]), "Colonization preserves each owner's occupied worlds")
|
||||||
|
var remaining_planets: Variant = 0
|
||||||
|
for id in ["GG", "AB", "RP", "HP"]: remaining_planets = E.add(remaining_planets, world.ledger.physical_amount(world.state, id))
|
||||||
|
check(E.eq(remaining_planets, E.multiply(count, 8)), "Planet loss equals colonies created")
|
||||||
|
invariants(world)
|
||||||
|
dispose(world)
|
||||||
|
print("Flow commit: %d checks, %d failures" % [checks, failures])
|
||||||
|
quit(1 if failures else 0)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://bfgdsxoycr20e
|
||||||
@@ -306,53 +306,84 @@ func _limit(plans: Dictionary, budget: Dictionary, rules: Dictionary) -> void:
|
|||||||
plans[source].counts[destination] = allowed
|
plans[source].counts[destination] = allowed
|
||||||
_merge(plans[source], source, rejected, plans[source].profiles[destination])
|
_merge(plans[source], source, rejected, plans[source].profiles[destination])
|
||||||
|
|
||||||
|
## Apply one conserved source-by-owner table, then credit each destination once.
|
||||||
func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules: Dictionary, year: Variant) -> void:
|
func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules: Dictionary, year: Variant) -> void:
|
||||||
var credits: Dictionary = {}
|
var credits: Dictionary = {}
|
||||||
var contributions: Dictionary = {}
|
var contributions: Dictionary = {}
|
||||||
var births: Dictionary = {}
|
var births: Dictionary = {}
|
||||||
|
var ownership: Dictionary = {}
|
||||||
|
var space_stages: Dictionary = {"Ct": true}
|
||||||
|
for id in rules: space_stages[id] = id == "Ct" or str(rules[id].home) != ""
|
||||||
|
for source in plans:
|
||||||
|
ownership[source] = {}
|
||||||
|
var free: Variant = target.amount.get(source, 0)
|
||||||
|
if E.gt(free, 0): ownership[source][""] = free
|
||||||
|
for owner in target.binds:
|
||||||
|
for source in target.binds[owner]:
|
||||||
|
if not ownership.has(source): continue
|
||||||
|
var held: Variant = target.binds[owner][source]
|
||||||
|
if E.gt(held, 0): ownership[source][owner] = held
|
||||||
for source in plans:
|
for source in plans:
|
||||||
var plan: Dictionary = plans[source]
|
var plan: Dictionary = plans[source]
|
||||||
var slots: Dictionary = {"": target.amount.get(source, 0)}
|
var remaining: Dictionary = {}
|
||||||
for owner in target.binds:
|
|
||||||
var held: Variant = target.binds[owner].get(source, 0)
|
|
||||||
if E.gt(held, 0): slots[owner] = held
|
|
||||||
for destination in plan.counts:
|
for destination in plan.counts:
|
||||||
var amount: Variant = plan.counts[destination]
|
var amount: Variant = plan.counts[destination]
|
||||||
if E.le(amount, 0): continue
|
if E.le(amount, 0): continue
|
||||||
|
remaining[destination] = amount
|
||||||
if not contributions.has(destination): contributions[destination] = []
|
if not contributions.has(destination): contributions[destination] = []
|
||||||
contributions[destination].append({"amount": amount, "profile": plan.profiles[destination]})
|
contributions[destination].append({"amount": amount, "profile": plan.profiles[destination]})
|
||||||
|
var slots: Dictionary = ownership[source]
|
||||||
|
target.amount[source] = 0
|
||||||
|
var owners: Array = slots.keys()
|
||||||
|
if owners.size() == 1 and owners[0] == "":
|
||||||
|
target.amount[source] = remaining.get(source, 0)
|
||||||
|
for destination in remaining:
|
||||||
if destination == source: continue
|
if destination == source: continue
|
||||||
var taken: Dictionary = Q.allocate_profiled(slots, amount)
|
var host: String = "@host" if space_stages.get(source, false) and not space_stages.get(destination, false) else ""
|
||||||
for owner in taken:
|
|
||||||
if E.le(taken[owner], 0): continue
|
|
||||||
slots[owner] = E.subtract(slots[owner], taken[owner])
|
|
||||||
var host: String = owner
|
|
||||||
if State.is_space_civilization(destination, rules) or destination == "Ct": host = ""
|
|
||||||
elif owner == "" and State.is_space_civilization(source, rules): host = "@host"
|
|
||||||
if not credits.has(destination): credits[destination] = {}
|
if not credits.has(destination): credits[destination] = {}
|
||||||
credits[destination][host] = E.add(credits[destination].get(host, 0), taken[owner])
|
credits[destination][host] = E.add(credits[destination].get(host, 0), remaining[destination])
|
||||||
target.amount[source] = slots[""]
|
continue
|
||||||
for owner in slots:
|
for i in owners.size():
|
||||||
if owner != "": target.binds[owner][source] = slots[owner]
|
var owner: String = owners[i]
|
||||||
|
# Last row receives the remaining exact quotas; the free-only path
|
||||||
|
# therefore needs no proportional allocation or repeated subtraction.
|
||||||
|
var allocation: Dictionary = remaining if i == owners.size() - 1 else Q.allocate_profiled(remaining, slots[owner])
|
||||||
|
for destination in allocation:
|
||||||
|
var amount: Variant = allocation[destination]
|
||||||
|
if E.le(amount, 0): continue
|
||||||
|
if i != owners.size() - 1:
|
||||||
|
remaining[destination] = E.subtract(remaining[destination], amount)
|
||||||
|
if destination == source:
|
||||||
|
if owner == "": target.amount[source] = amount
|
||||||
|
else: target.binds[owner][source] = amount
|
||||||
|
continue
|
||||||
|
var host: String = owner
|
||||||
|
if space_stages.get(destination, false): host = ""
|
||||||
|
elif owner == "" and space_stages.get(source, false): host = "@host"
|
||||||
|
if not credits.has(destination): credits[destination] = {}
|
||||||
|
credits[destination][host] = E.add(credits[destination].get(host, 0), amount)
|
||||||
|
if owner != "" and E.le(allocation.get(source, 0), 0): target.binds[owner][source] = 0
|
||||||
var hosts: Dictionary = {}
|
var hosts: Dictionary = {}
|
||||||
for id in physical:
|
for id in physical:
|
||||||
if world.catalog.entities[id].event_group == "DwStar" and E.gt(physical[id], 0): hosts[id] = physical[id]
|
if world.catalog.entities[id].event_group == "DwStar" and E.gt(physical[id], 0): hosts[id] = physical[id]
|
||||||
|
var host_shares: Array = _host_shares(hosts) if not hosts.is_empty() else []
|
||||||
for destination in credits:
|
for destination in credits:
|
||||||
var created: Variant = world.ledger.credit(target, destination, Q.sum(credits[destination]))
|
var created: Variant = world.ledger.credit(target, destination, Q.sum(credits[destination]))
|
||||||
|
var bound: Variant = 0
|
||||||
for owner in credits[destination]:
|
for owner in credits[destination]:
|
||||||
var count: Variant = credits[destination][owner]
|
var count: Variant = credits[destination][owner]
|
||||||
if owner == "" or E.le(count, 0): continue
|
if owner == "" or E.le(count, 0): continue
|
||||||
if owner == "@host":
|
if owner == "@host":
|
||||||
if hosts.is_empty(): continue
|
if hosts.is_empty(): continue
|
||||||
var ownership: Dictionary = Q.split_profile(target.civilization_remainders, "flow:hosts:" + destination, count, hosts.keys(), _host_shares(hosts))
|
var distributed: Dictionary = Q.split_profile(target.civilization_remainders, "flow:hosts:" + destination, count, hosts.keys(), host_shares)
|
||||||
for host in ownership:
|
for host in distributed:
|
||||||
if E.le(ownership[host], 0): continue
|
if E.le(distributed[host], 0): continue
|
||||||
if not target.binds.has(host): target.binds[host] = {}
|
if not target.binds.has(host): target.binds[host] = {}
|
||||||
target.binds[host][destination] = E.add(target.binds[host].get(destination, 0), ownership[host])
|
target.binds[host][destination] = E.add(target.binds[host].get(destination, 0), distributed[host])
|
||||||
target.amount[destination] = E.subtract(target.amount[destination], count)
|
|
||||||
else:
|
else:
|
||||||
target.binds[owner][destination] = E.add(target.binds[owner].get(destination, 0), count)
|
target.binds[owner][destination] = E.add(target.binds[owner].get(destination, 0), count)
|
||||||
target.amount[destination] = E.subtract(target.amount[destination], count)
|
bound = E.add(bound, count)
|
||||||
|
target.amount[destination] = E.subtract(target.amount[destination], bound)
|
||||||
if not rules.has(destination): births[destination] = created
|
if not rules.has(destination): births[destination] = created
|
||||||
var final: Dictionary = world.ledger.physical_amounts(target)
|
var final: Dictionary = world.ledger.physical_amounts(target)
|
||||||
for destination in contributions:
|
for destination in contributions:
|
||||||
@@ -387,7 +418,7 @@ func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: D
|
|||||||
var total: Variant = Q.sum(granted)
|
var total: Variant = Q.sum(granted)
|
||||||
if E.le(total, 0): return
|
if E.le(total, 0): return
|
||||||
var taken_resources: Dictionary = Q.allocate_profiled(stocks, total)
|
var taken_resources: Dictionary = Q.allocate_profiled(stocks, total)
|
||||||
var remaining: Dictionary = granted.duplicate()
|
var removed_by_owner: Dictionary = {}
|
||||||
for resource in taken_resources:
|
for resource in taken_resources:
|
||||||
var removed: Variant = taken_resources[resource]
|
var removed: Variant = taken_resources[resource]
|
||||||
if E.le(removed, 0): continue
|
if E.le(removed, 0): continue
|
||||||
@@ -401,15 +432,30 @@ func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: D
|
|||||||
if E.le(amount, 0): continue
|
if E.le(amount, 0): continue
|
||||||
if owner == "": target.amount[resource] = E.subtract(target.amount[resource], amount)
|
if owner == "": target.amount[resource] = E.subtract(target.amount[resource], amount)
|
||||||
else: target.binds[owner][resource] = E.subtract(target.binds[owner][resource], amount)
|
else: target.binds[owner][resource] = E.subtract(target.binds[owner][resource], amount)
|
||||||
var allocation: Dictionary = Q.allocate_profiled(remaining, amount)
|
removed_by_owner[owner] = E.add(removed_by_owner.get(owner, 0), amount)
|
||||||
|
var remaining: Dictionary = granted.duplicate()
|
||||||
|
var placements: Dictionary = {}
|
||||||
|
var owners: Array = removed_by_owner.keys()
|
||||||
|
for i in owners.size():
|
||||||
|
var owner: String = owners[i]
|
||||||
|
var allocation: Dictionary = remaining if i == owners.size() - 1 else Q.allocate_profiled(remaining, removed_by_owner[owner])
|
||||||
for destination in allocation:
|
for destination in allocation:
|
||||||
var count: Variant = allocation[destination]
|
var count: Variant = allocation[destination]
|
||||||
if E.le(count, 0): continue
|
if E.le(count, 0): continue
|
||||||
remaining[destination] = E.subtract(remaining[destination], count)
|
if i != owners.size() - 1: remaining[destination] = E.subtract(remaining[destination], count)
|
||||||
var created: Variant = world.ledger.credit(target, destination, count)
|
if owner == "" or State.is_space_civilization(destination, rules): continue
|
||||||
if owner != "" and not State.is_space_civilization(destination, rules):
|
if not placements.has(destination): placements[destination] = {}
|
||||||
target.amount[destination] = E.subtract(target.amount[destination], created)
|
placements[destination][owner] = count
|
||||||
target.binds[owner][destination] = E.add(target.binds[owner].get(destination, 0), created)
|
for destination in granted:
|
||||||
|
var count: Variant = granted[destination]
|
||||||
|
if E.le(count, 0): continue
|
||||||
|
world.ledger.credit(target, destination, count)
|
||||||
|
var bound: Variant = 0
|
||||||
|
for owner in placements.get(destination, {}):
|
||||||
|
var held: Variant = placements[destination][owner]
|
||||||
|
target.binds[owner][destination] = E.add(target.binds[owner].get(destination, 0), held)
|
||||||
|
bound = E.add(bound, held)
|
||||||
|
target.amount[destination] = E.subtract(target.amount[destination], bound)
|
||||||
for id in granted:
|
for id in granted:
|
||||||
if E.le(granted[id], 0): continue
|
if E.le(granted[id], 0): continue
|
||||||
var profile: Dictionary = colonies[id].profiles[id]
|
var profile: Dictionary = colonies[id].profiles[id]
|
||||||
|
|||||||
Reference in New Issue
Block a user