700 тысяч строк кода, 20 лет и один разработчик: как строится Dwarf Fortress

700тысячстроккода20летиодинразработчиккакстроитсяdwarffortress

Dwarf Fortress – один из тех странных проектов, которые проникли в сознание Интернета. Это бесплатная игра, в которой вы играете либо за авантюриста, либо за крепость, полную гномов, в случайно созданном фантастическом мире. Симуляция проходит глубоко, с новыми играми, создающими множество цивилизаций с историями, мифологиями и артефактами.

Это стало печально известным, и это правильно. У отдельных дварфов есть эмоциональные состояния, любимые драгоценности и обиды. И все это происходит в интерфейсе ASCII, который выглядит впечатляюще для новичков, но похоже на ползание текста в Матрице : ремесленник, река, легендарное чудовище.

Вся игра является продуктом одного разработчика, Тарна Адамса, также известного как Toady One, который работает над Dwarf Fortress с 2002. Первые четыре года это был проект на неполный рабочий день, но с 2006 он был полностью занят. Он сам пишет весь код, хотя его брат помогает с дизайном и создает истории на основе игры. До сих пор он полагался на пожертвования, чтобы поддерживать его, но в настоящее время он работает над версией с пиксельной графикой и обновленным пользовательским интерфейсом, которая будет доступна для покупки в Steam.

Я обратился к Тарну Адамсу, чтобы узнать, как ему удалось создать единую растущую кодовую базу, превышающую 15 + годы, опасности пути и отладки мертвых кошек. Наш разговор ниже был отредактирован для ясности.


Q : Какие языки программирования и другие технологии вы используете? В принципе, какой у вас стек? Изменилось ли это за лет вы этим занимаетесь?

A : DF – это некоторая комбинация C и C ++, а не своего рода стандартный способ подчинения, но своего рода беспорядок, который нарастает со временем. Я использую Microsoft Visual Studio с MSVC 6, хотя сейчас я использую какую-то версию Visual Studio Community.

Я использую OpenGL и SDL для решения проблем с движком. Мы пошли с ними, потому что их было легче перенести на OSX и Linux, хотя я, конечно, все еще не мог этого сделать. Я не уверен, что использовал бы сейчас что-то вроде Unity или Unreal, если бы у меня был выбор, поскольку я не знаю, как использовать ни один из них. Но работа с собственным движком также является настоящей проблемой, особенно сейчас, когда я занимаюсь чем-то помимо текстовой графики. Для звука использую FMOD.

Все это было постоянным на протяжении всего проекта, за исключением того, что SDL был введен через несколько лет, чтобы мы могли делать порты. Что касается механической части игры, я не использую много сторонних библиотек, но время от времени я подбирал некоторые вещи, генерирующие случайные числа – я вставляю Mersenne Twister давным-давно, и совсем недавно я принял SplitMix 64 , о котором говорилось на последнем празднике Roguelike Celebration.

Q : Какие проблемы возникают при разработке одного проекта так долго? Как вы думаете, это проще сделать самому? То есть, поскольку вы написали каждую строку, легче ли ее поддерживать и изменять?

A : Легко что-то забыть! Выполняя поиск ‘;’, что является свободным методом, но достаточно близким, мы получаем , 07, так что это просто невозможно сейчас все это держать в голове. Я стараюсь называть свои переменные и объекты последовательно и запоминающимся образом и оставляю достаточно комментариев , чтобы напомнить себе о том, что происходит. когда я дойду до места с кодом. Иногда требуется несколько поисков, чтобы найти точную нить, которую я пытаюсь продолжить, когда я возвращаюсь к какой-то части игры, к которой не прикасался десять лет, что случается довольно часто. Я бы сказал, что большинство изменений сосредоточено только на определенных частях игры, поэтому есть активный расплавленный ядро, о котором я знаю гораздо лучше. Есть несколько действительно крутых моментов, на которые я не обращал внимания с момента выхода первого выпуска в 2021 .

Что касается относительной простоты самостоятельной работы, то, конечно же, для меня, у которого нет опыта работы над большим проектом, состоящим из нескольких человек, это правильный путь! Люди, очевидно, хорошо умеют делать это по-другому, например, в контексте игр AAA, и очевидно, что там требуется несколько инженеров, чтобы все делать вовремя. Я бы не решился сказать, что могу пойти и изменить вещи быстрее, чем они, обязательно, так как я раньше не работал в этом контексте, но это правда, что у меня нет никаких командных или бюрократических препятствий, чтобы прыгать через, когда я хочу внести изменения. Я могу просто пойти и сделать это. Но я тоже должен делать это в одиночку.

Q : Какой самый большой рефакторинг / изменение, которое вам пришлось сделать?

A : Были некоторые рефакторы, которые длились месяцами, переделывая определенные структуры данных и так далее, хотя я не уверен, что здесь что-либо может быть строго рефакторингом, поскольку всегда есть возможности одновременно продвинуть механику вперед, и это имеет смысл делать, когда знания кода свежие.

Добавление координаты Z для механического преобразования игры в 3D (при этом оставаясь текстом) было еще одним и действительно самым утомительным занятием, которое я, вероятно, когда-либо делал. Всего несколько недель, недель и недель принятия логических и функциональных вызовов, основанных на X и Y, и наблюдения за тем, как Z вписывается в них.

Создание полиморфной системы элементов было в конечном итоге ошибкой, но это был большой.

Q : Почему это была ошибка?

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

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

Я думаю, что некоторые разработчики игр называют это системой компонентов сущности, хотя, насколько я понимаю, люди, занимающиеся оптимизацией более жесткого ядра, думают об этом как о чем-то еще, где вы на самом деле разбиваете вещи на отдельные поля. Использование одного объекта с разными выделенными подобъектами почти наверняка хуже из-за промахов в кэше, что совсем другое, но преимущества в организации, гибкости и расширяемости просто нельзя игнорировать, а разные подполя элемента инструмента не t используется так часто, что становится проблемой оптимизации.

Q : Сталкивались ли вы с какими-либо проблемами при переходе с 32 бит на 64 немного? Это похоже на одну из тех вещей, которые были огромными в то время, но стали довольно популярными.

А : Вовсе нет! Я изо всех сил пытаюсь придумать хоть одну проблему. К счастью для нас, мы уже довольно хорошо контролировали размеры байтов, поскольку это касается сохранения и загрузки миров; формат нужно было вернуть обратно, когда мы его настраивали, особенно потому, что нам приходилось иметь дело с порядком байтов между операционными системами и всем остальным. И мы не выполняем никаких грубых операций с указателями или других вещей, которые могли бы доставить нам неприятности. Он просто оказался действительно хорошим кодом для 90 битового преобразования благодаря нашему другие практики, совершенно случайно. Основная проблема заключалась в том, чтобы просто собрать время, чтобы внести изменения, и в итоге это заняло не так много времени, как я ожидал.

Q : Я видел других игры, похожие на DF, умирают из-за своих алгоритмов поиска пути. Что вы используете и как поддерживать его эффективность?

A : Да, базовый алгоритм – это только его часть. Мы используем A , что, конечно, быстро, но само по себе этого недостаточно. Мы не можем воспользоваться некоторыми нововведениями в этой области (например, точка перехода ), поскольку наша карта так сильно меняется. Как правило, люди использовали подходы, которые добавляют различные более крупные структуры поверх карты, чтобы срезать углы, и из-за изменения карты они просто требуют слишком много времени для обслуживания или по другим причинам создают проблемы. Таким образом, наш подход заключался в том, чтобы просто отслеживать подключенные компоненты, до которых можно добраться пешком. Их довольно легко обновить, даже если карта меняется быстро, хотя это требует некоторого заполнения. Например, если вода разрезает крепость пополам, она должна вылиться с одной стороны и обновить целую половину крепости до нового индекса, но как только это будет сделано, в целом это хорошо. Затем это позволяет нам исключить из игры почти все неудавшиеся вызовы A – нашим агентам просто нужно запросить номера компонентов, и если номера компонентов совпадают, они знают, что вызов будет успешным.

Его быстро поддерживать, но недостатком является то, что индексы компонентов поддерживаются только для ходьбы. Это означает, что летающие существа, например, не обладают глобальным интеллектом поиска пути, который ничем не отличается от интеллекта ходячих. В бою и некоторых других ситуациях мы используем заливки ближнего действия с их реальной логикой, чтобы дать им некоторые преимущества. Но для них это не идеально.

Я не уверен, что мы попробуем другие структуры здесь, чтобы заставить его работать лучше. Для наших размеров карты все они потерпели неудачу, включая некоторые попытки извне. Конечно, это может быть возможно при действительно согласованных усилиях, и я видел другие игры, в которых использовались, например, некоторые прямоугольные наложения и т. Д., Которые кажутся многообещающими, но я не уверен, насколько изменчивыми или большими были их карты .

Самая простая идея – это что-то вроде добавления нового индекса для листовок, но это большой удар по памяти и скорости, поскольку нам нужно поддерживать два индекса одновременно, и один достаточно плохо. Более конкретные наложения могут отслеживать их свойства пути (а затем вы проходите через наложения вместо плиток), но их сложно и медленно поддерживать при изменении карты. Существуют и другие идеи, такие как отслеживание лестниц или кэширование ограниченного пути, и, вероятно, в этом можно будет кое-что улучшить. Мы определенно находимся на грани того, что мы можем поддерживать в настоящее время с точки зрения агентов и сложности карты, поэтому нам придется кое-что дать, если мы хотим получить от этого больше.

Q : На этой ноте вы моделируете множество вещей одновременно – как вам удается асинхронно управлять таким количеством актеров (или вы)?

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

Q : Пробовали ли вы другие проекты / технологии помимо DF?

A : Конечно! Папка стороннего проекта, которая переносилась между компьютерами за последние десять лет или около того, имеет около 281 проекты в нем. Некоторые из них длились несколько дней, некоторые – несколько лет. В основном это другие игры, почти всегда в других жанрах, но есть также несколько вспомогательных проектов DF, таких как прототип генератора мифов. Ничего похожего на дневной свет, но забавно поиграть.

Q : С твоей ~ 90 сторонние проекты, изучали ли вы какие-либо другие программы? mming языки? Если да, то какие любимые?

A : Ха-ха, нет! Я больше занимаюсь дизайном, чем технологиями. Я уверен, что некоторые вещи действительно ускорили бы реализацию моих проектов, поэтому мне, вероятно, следует хотя бы выучить некоторые сценарии и побольше поиграть с потоками. Люди даже были достаточно любезны, чтобы предоставить некоторые библиотеки и вещи, чтобы помочь там, но просто трудно заблокировать время побочного проекта для технического обучения, когда мое время побочного проекта – для отдыха.

Q : У вас есть самые интересные примечания к выпуску. Какая ваша любимая ошибка и чем она вызвана?

A : Мне, наверное, скучно говорить, но я просто не могу победить пьяного кошачьего жука. К этому моменту было снято несколько видео об этом. Это был тот случай, когда кошки были обнаружены мертвыми по всему полу таверны, и оказалось, что они глотали пролитый алкоголь, когда чистили лапы. Одно число отсутствовало в коде «Проглатывание во время очистки», и оно отправляло их через все симптомы отравления алкоголем (которые мы добавили, когда приводили в порядок ядовитых существ)

Теги: , ,