D:\sideБлогStarbound: случайности не случайны

⚠️ Обращайте внимание на даты.
Этот блог больше не ведётся с 17 января 2023, и на тот момент с написания этой страницы (18.12.2013) прошло 9 лет.

Пришло время для очередного поста, который от профессиональной деятельности скорее далёк, и потому отправляется именно сюда.

Пару недель назад вышла в открытую бету игра, которую ждали достаточно многие, чтобы кампания краудфандинга (вроде нашумевшего Kickstarter) собрала больше двух миллионов долларов. Многие язвительно выражаются, что у Terraria появился новый клон - чаще всего это люди, не особенно в Terraria игравшие. Различия видны с первого же взгляда. А уж у тех, кто Terraria “прошёл” (выдержал 15-ую тыквенную волну?) утверждение об очередном клоне часто вызывает неожиданный (и бурный!) поток ненависти и аргументов. Что, обычно, выглядит скорее смешно.

Здесь я попробую объяснить, на что изначально замахивался проект, что из этого ему удалось и какими методами. Потому что пристальный взгляд на Starbound приоткрывает некоторые интересные приёмы и тайны, скрытые за красивыми словами “особенностей игры”.

Итак, Starbound. Проект долгое время (которое он существовал в виде идеи) можно было назвать “Террарией с процедурной генерацией вообще всего”. То есть, тоже мир из блоков, тоже оружие ближнего и дальнего боя, шляющиеся по поверхности монстры, строительство собственных домов, копание в шахте. И магия начинается, когда той планеты, на которой вы начали играть, вам становится мало.

В мультиплеере Terraria такая проблема постепенно возникает сама собой. Мир ограничен, в нём фиксированное количество руды, и она разбросана по миру, как придётся. Большинство игроков прокапывает дыры здесь и там, выкапывает руду, строит дома, и постепенно оказывается, что по миру, не спотыкаясь, пройти просто невозможно. Игроки на одном и том же мире просто не могут ужиться достаточно долго.

В Starbound развитие изначально предполагает, что вы посетите не один мир. Поэтому генератор мира сделан совсем иначе - он запускается не перед тем, как вы начинаете игру, а уже в то время, что она вовсю идёт. Генератор достаточно быстрый, чтобы собирать мир прямо в процессе вашей высадки. И в одной и той же вселенной за время “прохождения” Starbound вы побываете на нескольких десятках, а то и сотнях планет. Возникает разумный вопрос - сколько занимает вся эта генерируемая вселенная, и не лопается ли сервер от таких объёмов?

Ответ: не лопается, потому что памяти на запоминание для вселенной нужно ровно столько, сколько кода требуется для воссоздания. Если вы интересовались тем, каким образом компьютер выдаёт случайные числа, то знаете, что “случайности не случайны”. Не бывает ничего абсолютно случайного, бывает что-то непредсказуемое доступными нам средствами. Тот же результат броска монеты, по сути, определяется характеристиками движения монеты, приданными ей при броске. То, что глазом мы скорее всего не уловим, какой стороной монетка приземлится, вина скорее глаза.

Проблема с этим возникает у пользователей GameMaker: Studio, которые перешли с более ранних версий - потому что Studio не утруждает себя вносом “настоящей” случайности при старте игры, и при каждом следующем запуске, если вы генерируете полсотни случайных чисел, вы будете получать одни и те же числа раз за разом. Жалобы просто не утихают, несмотря на то, что в документации этот эффект описан вместе со способом противодействия ему.

Для кого-то такой эффект может показаться нежелательным, хоть его и легко избежать. Но проблема в том, что иначе компьютеры просто не умеют. Известный сервис Random.org вносит “настоящую случайность” (умным словом: “энтропию”) шумами в атмосфере, которые предсказать почти невозможно. Это для тех, кому настоящая случайность действительно необходима. Для некоторых хватит внесения случайности на основе того, в какой момент реального времени (согласно часам компьютера) игра запущена. Но есть и обратная сторона у такого поведения.

Псевдослучайность позволяет, вооружившись одним числом, получить целую последовательность чисел, возникающих по непонятно какому (но определённому) закону. Причём последовательность любого размера. А вооружившись двумя способами генерации одних случайных чисел из других, можно из случайной “одномерной” последовательности чисел получить “двумерную”: эдакую последовательность последовательностей случайных чисел. Больше способов - больше чисел, причём база для их генерации весит очень мало (пара чисел, несколько формул), а объём получаемых данных колоссален.

К чему всё это. Starbound заявляет, что мир игры бесконечен. Это не совсем так. Но мир настолько огромен, что ни один человек за всю свою жизнь вручную не сумеет обследовать все планеты в игре.  Можно говорить о “практической бесконечности” (от слова “практика”, а не в значении “почти”), то есть, по сути своей о чём-то, величина чего известна и конечна, но попытки увидеть всё займут колоссальное время. И сервер игры не обязан хранить всю вселенную в собранном состоянии - он может её воссоздавать на основе данных, получаемых из сложной структуры случайных данных.

Ещё одно забавное следствие такой “псевдослучайности”:  вселенная у всех игроков и на всех серверах абсолютно одинакова. То есть, два разных человека, вбившие одни и те же координаты на двух разных компьютерах попадут на одну и ту же планету. Разумеется, они увидят друг друга и изменения друг друга только в том случае, если они на одном сервере - но точка высадки, животные, растения, рельеф и условия на планете будут идентичными. Потому что планета процедурно генерируется на основе некоторых псевдослучайных данных.

Почему это хорошо: потому что это лишний способ для игроков помочь друг другу в развитии - найдя интересную вещицу, ты можешь сказать координаты планеты с ней другу, он прилетит на неё в одиночной игре и тоже её там найдёт. Почему это, кажется, плохо: потому что мир получается у всех один и тот же, никакой (казалось бы) случайности. Вот только стартуют все созданные персонажи в разных точках вселенной , поэтому кажется, что всё случайно. Это, впрочем, подтвердилось только для одиночной игры, в мультиплеере несколько зашедших на сервер свежими персонажами людей оказались на одной планете, экспериментальный факт. Что даже хорошо - ко-оп (совместное прохождение) начинается сразу же, без необходимости дополнительной передачи координат и лишних перелётов.

Но даже несмотря на космическое (почти буквально) мастерство использования псевдослучайных данных, генерация многих элементов игры производится на манер конструктора, то есть, сборки из предопределённого набора готовых элементов. Сами элементы не генерируются алгоритмами, а сделаны заранее. Обладатели Starbound могут в этом убедиться, просто полазив по папке assets, по которой можно даже составить представление о том, как собираются некоторые графические элементы. Планеты на навигаторе, например, состоят из основы (круг), картинки поверхности (рельеф) и маски (освещение) (можно ещё атмосферу добавить, облака). Собрать их вместе - получится планета. Имея, скажем, по 6 штук каждого вида ресурса, получим \(6 \cdot 6 \cdot 6 = 36 \cdot 6 = 216 \) разных картинок планет.  Добавляем цветовые вариации отдельных компонентов, хотя бы с шагом \(32\) из возможных \(256\) (\(8\) вариаций только оттенка, без насыщенности), получается \(1728\), если делать разные оттенки поверхности. И это только первые прикидки, на которые даже не нужно много времени. Если добавить туда вариации животных, растений, опасностей, минералов, рельефа, получается огромное количество. Этим Starbound и пользуется, чтобы создать мир, который весь не объездишь.

Хотя надо отметить, что жизнь на абсолютно всех планетах кажется подозрительным допущением. Starbound генерирует планеты не из тех элементов, которые могут привести к ужасающим для жизни условиям на планете. Впрочем, попадаются экземпляры, где самый лучший источник освещения - забредшее в лужу лавы местное животное. Как бы жестоко это ни звучало. Осваивая космос, насмотришься на всякое. На тему тяжёлых космических будней я вам ещё много расскажу.