Files
owniverse/simulation_rules.md
T

27 KiB
Raw Blame History

Эволюция звёзд Owniverse.GI

Механики перенесены из Owniverse.U с согласованными изменениями GI: постепенные партии, детерминированные дробные остатки, уязвимость цивилизаций до C1.2 и передача выживших планет преемнику. Баланс таблицы GI сохраняется.

Порядок расчёта

  1. Накопить игровое время; обработать новые десятые доли года.
  2. Рассчитать производство существующих объектов за интервал с учётом их постепенного исчезновения; выполнить автоматическое создание звёзд и их планет.
  3. Для очередного поколения определить долю заканчивающих жизнь звёзд. Применить локальное разрушение их планет до списания партий.
  4. Снять целые объекты из партий, рассчитать основные и альтернативные выходы с накоплением дробей.
  5. Передать выжившие планеты полученным звёздам/остаткам. Если преемников несколько, распределить по их фактическим количествам; если преемника нет — освободить. Остальные связанные объекты используют существующие правила GI.
  6. Создать партии преемников. Учесть производство новорождённых за оставшуюся часть длинного шага, включая излучение короткоживущих сверхновых.
  7. Применить суммарный бласт поколения; повторять обработку поколений, пока в интервале остаются переходы.
  8. Пересчитать группы и опубликовать состояние.

Автоматическое создание бурых карликов

На горячие бурые карлики HBD выделяется 0,1% нового фактически произведённого автоматического водорода за расчётный интервал. По текущей таблице автоматическую долю имеют STN (auto = 0.5) и ASTN (auto = 0.65). Обычный водород, ручные покупки и неиспользованный запас прошлых интервалов повторно в эту долю не входят.

При стоимости c = 0.1 H квота объектов увеличивается на ΔQ = ΔH_auto × 0.001 / c. Она хранится между циклами и в сохранении в auto_star_deficits.HBD. Доступность ограничивается автоматическим запасом и уже оплаченным топливом: Q ≤ (auto_resources.H + HBD_fuel) / c.

Карлики появляются по одному. Для q = max(0, Q) создаётся floor(q) объектов и ещё один с вероятностью q - floor(q), с ограничением по доступному топливу. Созданное количество вычитается из Q; отрицательный остаток компенсирует досрочное появление на следующих шагах. Повторного случайного округления без нового автоматического водорода нет. Это исключение из общего детерминированного округления GI. Состояние генератора auto_star_deficits.HBD_random сохраняется, поэтому загрузка продолжает ту же последовательность.

Водород списывается целыми единицами авансом: charge = ceil(max(0, count × c - HBD_fuel)). Неиспользованный остаток HBD_fuel += charge - count × c сохраняется в auto_star_deficits.HBD_fuel и больше не входит в свободный запас или бюджет обычных звёзд. Например, 500 автоматических H позволяют создать 5 HBD, списав 1 H и оставив 0,5 H оплаченного топлива. Следующие 5 HBD используют этот остаток без повторного списания. Численность всегда целая, но не обязана быть кратной 10. При отсутствии обычных звёзд их доля остаётся в запасе, а производство HBD всё равно работает.

Новые HBD получают обычные жизненные партии. По таблице их срок — 5 миллиардов лет, затем они постепенно превращаются в холодные CBD. На экране оба типа суммируются в BD. Ручного рецепта у общего счётчика BD нет. Миграция сохранений не требуется: квота использует существующий словарь, отсутствующее значение равно нулю.

Постепенные партии

Короткоживущие звёздные события внутри длинного шага

Для SN, DSN, BSN, HN и GRB-событий полностью завершившиеся окна рождения не создают отдельные словари партий. Их целые количества суммируются в очередь завершений текущего расчёта; обычные партии сохраняются только для окон, срок которых ещё не закончился. Состояние этой очереди не записывается в сохранение: она полностью обрабатывается до публикации нового состояния.

Окно завершено, если window_end + lifespan ≤ to_year. Его доля количества рассчитывается прежним методом разности накопленных целых значений. Для производства пространства интеграл исчезновения вычитается по окнам в прежнем порядке, чтобы сохранить округление. Здесь остаётся лёгкий арифметический проход по окнам, но отсутствуют создание, копирование, сортировка и последующая обработка тысяч временных словарей.

Ресурсы, остатки звёзд и бласты от завершившейся части применяются на следующем поколении расчёта, как раньше. Поэтому сохраняются порядок передачи привязок, среда бластов и ограничения цивилизаций. Ускорение допускается только для событий группы SNGRBB с линейным выходом и без преемников с ненулевым сроком жизни. При изменении таблиц остальные случаи автоматически используют обычный путь. Сроки жизни и ширина окон не увеличиваются, формат сохранения не меняется.

На сохранении возраста 140,55 млн лет, при шестой скорости и шаге 1/60 секунды: максимальное временное число партий SN/GRB уменьшилось с 1668 до 2; средний расчёт кадра без отрисовки — примерно с 15 до 10 мс. За 120 шагов результаты старого и нового путей совпали по всем полям состояния. Эти значения характеризуют конкретное сохранение, а не гарантированную частоту кадров на всех устройствах.

Общие окна рождения и эволюции

Окно рождения шириной w = lifespan / 40 при lifespan > 10, иначе w = lifespan. Окно превращения сдвинуто на lifespan. При частичном списании:

expected = remainder + (remaining_count - remainder) * elapsed / remaining_window
converted = floor(expected)
remainder = expected - converted

Конец окна списывает остаток. Переход не уничтожает всю партию в начале окна. Начала и длительности сохраняют модель GI, включая годовую длительность событий SN/GRB.

Планеты

При ручном и автоматическом создании звёзд:

expected = stars_created * planet_amount * planet_chance * metallicity + remainder
planets_created = floor(expected)
remainder = expected - planets_created

Остаток независим для каждой пары звезда/планета и сохраняется. Планеты сразу связаны со звездой. Эволюционный переход сам по себе не создаёт новую планетную систему. Шансы планет в таблице — доли, а проценты альтернативных выходов звёзд делятся на 100.

Среда: адаптация формул Unity к состоянию GI

GI не хранит накопленные счётчики первичной материи Unity. Поэтому stellar_environment() вычисляет среду из текущего физического состава, включая связанные объекты, без суммирующих групп интерфейса. Это приближение для баланса GI, а не побитовое воспроизведение Unity.

  • M — свободные и связанные H/He/Met плюс табличная масса конкретных объектов и масса SMBH.
  • V — физическое S плюс табличный объём объектов и voids * 1e22.
  • Z = max(0, 0.4 * ln(100 * free_Met / M + 0.11) + 0.88); при M = 0 металличность нулевая.
  • B = 65536 * f(M), где f(0)=1, f(M)=M^0.1 при 0<M<1e10, иначе 10.
  • density = 1.23456e-7 * sqrt(B + M) / max(1, V)^(1/6).
  • blast_factor = clamp(free_S / V, 0, 1); при нулевом объёме 1.

Система сил Unity и планетные бонусы в GI пока не перенесены; здесь используются нейтральные множители 1. Металличность для производства фиксируется до расходования ресурсов на звёзды. Среда бласта фиксируется для поколения до добавления его продуктов.

Разрушение и бласты

Локальное воздействие: ratio = dying_stars / physical_stars, без множителя плотности.

Бласт: hits = floor(power * blast_factor + saved_remainder). Распределение экспозиции между типами звёзд, имеющими планетные системы в таблице, пропорционально их физическому количеству. Для типа: ratio = hits * star_share / physical_stars * density.

Для каждого связанного типа планет накапливается held_planets * min(1, ratio). Уничтожается целая часть, не больше существующего количества. Остатки локального воздействия и бластов раздельны. Это позволяет слабым воздействиям работать при постепенной эволюции.

Уровень 1 превращает только blastability=1 в RP (HP, EON, цивилизации до C1.2). C1.3 и выше защищены от этого уровня. Уровень 2 уничтожает все планеты, включая защищённые цивилизации, без создания RP. Уничтоженные объекты удаляются из жизненных партий, чтобы не возникать заново.

Единственный источник мощности — поле blast сущности: power = expired_count × max(0, entity.blast). При blast = 0 внешнего воздействия нет. Старые вхождения blast:N в output игнорируются, включая альтернативные выходы; двойного суммирования нет. Внутренний выход blast остаётся событием, а не предметом. destroy_level независимо задаёт уровень локального разрушения у умирающего объекта; внешние бласты всегда действуют на уровне 1.

Границы этапа

Рассчитываются агрегаты по типам, а не отдельные звёздные системы; конкретная принадлежность каждой планеты отдельной звезде не моделируется. Распределения целых объектов детерминированы. Порядок внутри длинного шага — по поколениям, поэтому нелинейное воздействие бластов и среды не обязано совпадать с серией более коротких шагов. Эволюция HP и эонов подключена ниже; эволюция цивилизаций и бонусы структур описаны ниже. Глобальная система сил остаётся отдельной механикой.

Проверки: tests/test_time.gd, tests/test_stellar_rules.gd. Сохранения игрока тестами не затрагиваются.

Первичная жизнь: HP → EON1 → … → EON5 → C0.0

Правила хранятся в data/life_rules.txt, исходные сроки и коэффициенты взяты из Unity civs.txt. В каждой обработанной части партии:

  • прогресс: count * progress + carry_progress;
  • деградация: count * degradation + carry_degradation;
  • остальная жизнь остаётся на прежней стадии и получает новую партию для следующей попытки.

Прогресс и деградация округляются вниз с сохранением остатков. Если оба накопленных исхода конкурируют за последнюю планету, распределяются только существующие объекты, а неиспользованный остаток переносится на следующую попытку. Деградация распределяется по весам fall; знаковые ошибки распределения также сохраняются.

Для всех шести стадий базовые доли за попытку — progress=0.00025, degradation=0.0025. Интервалы HP/EON1/EON2/EON3/EON4/EON5: 5 млн, 10 млн, 10 млн, 1 млн, 1 млн, 500 тыс. лет. Используются постепенные окна GI шириной span / 40. Случайные множители Unity не применяются; агрессия, порядок и просвещение пока имеют нейтральное влияние.

HP деградирует в RP. У эонов возможен откат к предыдущим стадиям по таблице. RP не развивается сам. C0.0 и C0.1 также развиваются: период 2000 лет, прогресс 0.0175, деградация 0.025. Переходы C0.0 → C0.1 → C0.2, откат C0.0 → EON5 и C0.1 → C0.0. Развитие C0.2 и выше подключено через этические правила. Конфликт civ_bonus устранён повторным импортом: бонусы структур совпадают с Unity. Для существующих этических цивилизаций пользователь выбрал равномерное распределение между шестью этиками с детерминированным целым остатком.

Переходы сохраняют количество планет и их хозяев, включая передачу преемнику звезды и разрушение бластом. Повторная попытка той же стадии не увеличивает статистику созданных объектов. Партии новых планет регистрируются при создании; недостающие партии старых HP/эонов — однократно при загрузке с текущим возрастом вселенной, без выдумывания их прошлого возраста. Состояние содержит life_version=2 (версия 1 также загружается) и life_remainders.

Миграция версии жизни 1 → 2 добавляет только недостающие партии C0.0/C0.1, сохраняя уже существующие партии HP и эонов.

Этические и космические цивилизации

civilization_rules.txt содержит 43 стадии по шесть этик из Unity. Они загружаются в Global.CivilizationRules и участвуют в расчёте партий. После C4.4 следует Ct: конечная стадия без новых жизненных партий.

Состояние ethics[stage][ethic] хранит целые количества. Для существующих цивилизаций без этик количество распределяется поровну в порядке m, l, w, d, c, b; остаток распределяется по одному в этом порядке. Существующее распределение сохраняется. При внешних потерях оно пропорционально сокращается.

Цивилизации с непустым home (C2.0–C4.4) освобождаются от прежних привязок без изменения общего количества. Общий механизм переходов больше не переносит планетную привязку на такого преемника. Структуры назначаются отдельно в civilization_homes; при возвращении к планетным стадиям цивилизации размещаются у имеющихся карликовых звёзд.

Правило среды согласовано: число космических цивилизаций ограничено звёздным ресурсом. Для стадии i расход ёмкости — population[i] * max(1, Stars[i]). Каждое семейство Home имеет общий бюджет для всех использующих его стадий; звёзды внутри структур также учитываются, но повторно не суммируются. SMBH учитывается по суммарной массе в эквиваленте звёзд, согласно решению пользователя.

Переход переиспользует резерв исходной стадии. При нехватке ёмкости неподдержанные переходы остаются на исходной стадии. Лимит применяется к общему механизму выходов партий и ручному созданию; расчёт прогресса C0.2+ использует тот же бюджет.

При загрузке и после эволюционных поколений избыток деградирует последовательно до поддерживаемой стадии. Приоритет получают существующие более развитые цивилизации; остаток бюджета достаётся младшим. Деградация переносит количество и этики, сокращает старые партии и регистрирует новые, не уничтожая цивилизации. C2.0 при избытке становится C1.9 и распределяется по имеющимся звёздам-карликам. Если карликов нет, C1.9 остаётся свободной — отсутствующая звезда не создаётся. Планетные стадии до C2.0 не расходуют отдельную звёздную ёмкость: у одной звезды могут быть несколько планет.

Резерв ёмкости логический: звёзды не расходуются и продолжают производить ресурсы. Общий бюджет пересчитывается из физических количеств, отдельная копия бронирований в сохранении не хранится.

Расчёт поколения C0.2–C4.4

  1. Из истёкшей части партии пропорционально выбираются представители шести этик. Для каждой этики читаются progress и degradation; целые исходы получаются с сохранением дробных остатков. Неудавшийся из-за лимита переход возвращается на исходную стадию.
  2. Прогресс ведёт на следующую стадию; деградация распределяется по весам fall конкретной этики. Повторные попытки не увеличивают статистику созданных цивилизаций.
  3. При флаге fights рассчитываются войны. Веса исходов — 1:2:3:3, доли прогресса победителей — 0:0.25:0.5:0.75; первый исход деградирует атакующих. Потери противников — 2:1:1.5:2 на войну. Два последних исхода дают 10 и 30 единиц побочного ущерба предыдущей стадии. Выбор участников ограничен живой популяцией, включая ещё не сработавшие партии; их партии сокращаются вместе с населением.
  4. Для обычного дрейфа веса своей/противоположной/каждой другой этики равны 196/0/1. Дипломатия умножает исходные численности на diplomacy_rate, затем нормирует к прежней численности. Флаг дипломатии действует на остающихся на стадии. При переходе в Ct этика сохраняется без дрейфа.
  5. При флаге colonizes создаются колонии на две стадии ниже отправителя. Цели — существующие GG, AB, RP, HP; колонизация заменяет цель и сохраняет её звёздную привязку. Веса дрейфа колонистов — 960/4/9. Исходная цивилизация не расходуется. Новая партия начинается в текущий игровой момент.
  6. После применения переходов пересчитываются этики, поклонение (Σ population × worship), бласты и ограничения среды. Число операций зависит от числа типов и партий, а не от числа цивилизаций.

Окна исходных партий сохраняют время переходов; несколько частей одного типа обрабатываются агрегированно между минимальным и максимальным временем. Побочный ущерб неистёкшим партиям применяется в текущий момент. Все остатки округления сохраняются в civilization_remainders, счётчики — в civilization_stats.

Структуры и периоды

Прямой claim задаёт структуру стадии и норму 1; каждая промежуточная стадия умножает норму на 10 до следующего claim. Начиная с C3.0 требуется соответствующий запас структур, общий для использующих его стадий. При потере запаса избыток деградирует. Этот бюджет действует одновременно со звёздным.

Размещение выбирает структуры в порядке убывания civ_bonus, начиная с соответствующего стадии claim. Прямое размещение ограничено числом структур; остальные разрешённые структуры при наличии дают общий бонус, как в Unity. Период новых партий равен span / средневзвешенный civ_bonus, для неразмещённой части множитель равен 1. Уже назначенные сроки партий не переписываются при изменении бонуса.

life_version = 3 добавляет часы существующим C0.2+ с момента загрузки; старые часы HP, эонов и начальных цивилизаций сохраняются. Ct не получает часы. Миграция выполняется однократно. Глобальные силы и их модификаторы не входят в этот перенос: используются нейтральные множители 1.