Документация Nyxtale

Платформа NyxtaleЯзык Nyx

Случайность и детерминизм

rand(), Mulberry32, rng_seed: почему превью и игрок обязаны прийти в одну концовку.

Случайность в истории воспроизводимая: одно и то же прохождение всегда даёт один и тот же бросок.

rand

@set roll = rand(1, 6)
@if roll >= 5 -> steady
@if roll == 1 -> disaster
narrator: Рука дрогнула, но фонарь удержался.
движок принял linebranch×2setjump×2

rand(a, b) даёт целое от a до b включительно. Границы — константы или выражения; если верхняя оказалась меньше нижней, движок вернёт нижнюю, а валидатор скажет об этом заранее.

Зерно

У прохождения есть зерно (rng_seed) — число, с которого начинается случайность. Оно фиксируется на старте, лежит в состоянии и попадает в сохранение вместе с флагами; каждый вызов rand двигает генератор на шаг вперёд.

Отсюда:

Один генератор на обоих движках

Генератор — Mulberry32, он записан в формате. Превью на TypeScript и приложение на GDScript выполняют одни и те же шаги над 32-битным беззнаковым числом и выдают бит в бит одинаковую последовательность; совпадение проверяется тестами соответствия на обеих сторонах.

Стандартный random языка здесь не используется: у каждого языка он свой, и два стандартных генератора не совпадают. По той же причине арифметика целочисленная.

Как этим пользоваться

Бросок один раз, читается много. Запишите результат во флаг и читайте флаг: два rand в двух условиях — это два разных броска, даже написанные рядом.

@set roll = 0
@set roll = rand(1, 20)
@if roll >= 15 -> success
@if roll <= 3 -> fumble
-> partial
движок принял branch×2set×2jump×3

Случайность лучше работает на оттенке, чем на развилке. Бросок, решающий судьбу героя, читается как несправедливость. Бросок, решающий, какой из трёх шорохов он услышит, делает вторую читку другой.

Проверка навыка — это rand плюс флаг персонажа. Тогда на бросок влияет то, что читатель успел накопить, а не только случайность (подробно — прогрессия):

@set nerve = 0
@set roll = 0
@set roll = rand(1, 20) + nerve
@if roll >= 14 -> steady_hand
-> shaking
движок принял branchset×3jump×2

Что дальше

Бот-обход стоит на том же детерминизме: он ходит по всем путям и приходит к одному отчёту дважды подряд.