опубликовали Villfuk02, redlabel, stringweasel, Nanogamer7, Conor_, Therenas, Firerazer
В этом восхитительном выпуске № 33 Alt-F4, Villfuk02 представляет свой последний созданный мод: The Recipe Randomizer! В центре внимания все проблемы дизайна, которые необходимо было преодолеть, чтобы сделать действительно хороший рандомизатор рецептов. После этого redlabel объявляет о событии COMFY, которое, скорее всего, будет довольно взрывным.
Vanilla: Взболтать, но не смешивать Villfuk02
Vill’s Recipe Randomizer делает именно то, что следует из названия — рандомизирует рецепты. На первый взгляд это может показаться очень глупой, но очень простой идеей. Однако, как только вы попытаетесь сделать его менее глупым, он довольно быстро станет очень сложным.

Как это началось
Впервые я начал работать над этим проектом в сентябре 2020 года. В то время я пытался сделать мод, который был бы одновременно простым и уникальным. Это не должно было быть играбельным или даже хорошим, просто что-то забавное. Столкнувшись с некоторыми проблемами, прекрасно зная, что я делаю мод, в который все равно никто не будет играть, я сдался и больше никогда не касался программирования.
После двух других неудачных проектов я вернулся в Factorio, на этот раз в качестве игрока. Я играл в ваниль, потом в Industrial Revolution 2, а потом попробовал Space Exploration. Мне нравится играть в моды , потому что они позволяют мне изучать новые рецепты, открывать новые схемы заводов и решать новые логистические проблемы. Но большинство модификаций очень утомительны, и мне быстро надоедают. Именно тогда я понял, что у мода рандомизатора на самом деле есть цель: это как неограниченный запас модов, сохраняя при этом ощущение ванили! Самым большим плюсом для меня было то, что мне не нужно было создавать какие-либо новые машины или графику, поскольку это просто возня с цифрами и буквами.
Не так просто, как кажется
Мод может просто взять каждый рецепт и сделать так, чтобы в качестве ингредиентов использовались случайные предметы. Это было бы довольно плохо, потому что, например, красная наука может использовать ядерное топливо в качестве ингредиента, но вы еще не изучили его. Поэтому я решил заставить его ползать по дереву технологий, и для каждого открываемого рецепта брать только те предметы, которые были разблокированы до него, в качестве потенциальных ингредиентов. Конечно, есть исключения в некоторых модах, где вы можете разблокировать рецепт еще до того, как сможете его создать, поэтому мне нужно быть немного осторожнее.
Вы, наверное, не захотели бы делать подземный конвейер из паровых машин и лабораторий. Это было бы слишком дорого. Мне нужен был способ сделать рецепты более сбалансированными. Поэтому я решил реализовать алгоритм, который вычисляет стоимость каждого элемента на основе ресурсов, необходимых для его изготовления. Нетрудно подсчитать, что на одну электронную схему уходит 1 железная руда и 1,5 медной руды:

Предположим, что и медная, и железная руда имеют значение 1, это означает, что электронные схемы будут иметь значение 2,5. Теперь рандомизатор знает, что он может использовать, например, один конвейер (значение 1,5) и одну медную руду (значение 1) в качестве нового рецепта для электронных схем. В окончательном значении есть некоторые расхождения. Это делает рецепты немного более уникальными, но, что наиболее важно, легче найти правильную комбинацию, что ускоряет процесс рандомизации.
На этом этапе я опубликовал мод, и из отзывов и некоторых тестов стало очень очевидно, что есть много ошибок (конечно) и две «большие» проблемы. Слово «большой» заключено в кавычки, потому что в этот мод по-прежнему выглядит лучше, чем можно было ожидать, даже от рандомизатора. Однако я хотел, чтобы игроки получали от этого удовольствие, а не просто испытывали его.
Первые несколько проблем
Первой было дерево. Настройки по умолчанию гарантируют, что древесина не будет рандомизирована, но во многих рецептах в качестве ингредиента использовались деревянные столбы! Как вы понимаете, исправление должно было быть довольно простым и скучным. Я добавил флаг для нерандомизируемых ресурсов, таких как дерево, и любого предмета, которому строго нужен предмет с этим флагом, поскольку его ингредиент наследует его.
Вторая заключалась в том, что, хотя рецепты требовали правильного количества ресурсов, они часто были слишком сложными и казались несправедливыми. В моде не учитывалось количество этапов создания или время изготовления. Отличным примером является пакет автоматизации (красный). Он очень дешевый, его стоимость всего 3, но на его изготовление уходит 5 секунд. Он использовался во многих рецептах как базовый компонент, как и железные шестерни. Его долгое время изготовления означает, что вам может понадобиться множество сборщиков, создающих красную науку только для чего-то простого, как подземные конвейеры. Другой проблемный пример заключается в том, что для простых предметов, таких как железные шестерни, может потребоваться много шагов, таких как изготовление их из каменных кирпичей, которые могут быть сделаны из железных палочек, которые могут быть сделаны из труб и т. Д. Поэтому я заставил мод вычислить второе значение, называемое сложностью. , для каждого элемента. Сложность учитывает количество необходимых этапов создания, количество различных ингредиентов (и результатов), а также время изготовления.
Баланс ресурсов
Казалось, что я пришел к идеальному рандомизатору, но опять же, некоторые проблемы (и ошибки) проявили себя. Часто во многих рецептах использовался в основном один ресурс (часто железо или камень), и вам приходилось искать далекие участки руды, потому что вам нужно было именно так много выбранного ресурса. Кроме того, для запуска ракеты часто не требовалось нефти. Для данного рецепта все подходящие предметы с одинаковой вероятностью были выбраны, поэтому количество предметов без нефти значительно превышало количество нескольких нефтепродуктов. Я пробовал несколько стратегий, чтобы продвинуть алгоритм в правильном направлении, но ни одна из них не сработала. Я мог бы просто сказать ему, чтобы он использовал больше пластика или твердого топлива и тому подобное, но что, если вы хотите поиграть с модами, и есть еще больше предметов, которым нужно уделять приоритетное внимание? Хотел универсальное решение.
Я уже знал один подход, который мог бы решить эту проблему, но я боялся реализовать его, потому что он все усложнил бы. Это означает больше времени на разработку, больше ошибок и, возможно, более медленную загрузку. После безуспешных попыток придумать более простой способ добиться аналогичного результата, я, наконец, решил пойти с этим сложным решением.
Основная идея заключалась в том, чтобы использовать количество сырых ресурсов, а не общую стоимость. Это означает, что мод может гарантировать, что каждый случайный рецепт требует правильного количества сырых ресурсов, обеспечивая использование всех сырых ресурсов. Подобно общему значению, количество ресурсов для каждого рецепта может немного отличаться, или они могут быть полностью случайными в зависимости от настроек мода. Довольно просто, правда? Что ж, теперь вместо того, чтобы заниматься математикой с одним числом, мне приходится вычислять с несколькими, а логика намного сложнее. К счастью, после некоторых оптимизаций и тщательного тестирования мод работает нормально и по-прежнему работает довольно быстро.
И это вся история Vill’s Recipe Randomizer!
Нам нужно идти дальше
За исключением того, что я не говорил о некоторых БОЛЬШИХ проблемах (обратите внимание на отсутствующие кавычки и заглавные буквы), которые присутствовали с самого начала. Один из них — циклические рецепты. Алгоритм мог застрять при попытке оценить значение одного из рецептов или вычислить его неправильно. С циклами, содержащимися в одном рецепте, легко справиться. Для оценки рецепта алгоритм вырезает элементы, которые появляются как в качестве ингредиента, так и в результате, удаляя цикл. Затем он может снова добавить нарезанные элементы, потому что их значения теперь известны, что делает рецепт готовым для рандомизации. В ванили это относится к процессу обогащения Kovarex и ожижению угля:

Циклы с более чем одним рецептом несколько проблематичны. В ванили нет циклов с более чем одним рецептом (кроме загрузки/выгрузки в бочки и , которые по умолчанию не рандомизируются), поэтому их довольно легко пропустить, но в модах они есть везде! Рандомайзер также может случайно создать цикл при определенных условиях. Чтобы проиллюстрировать проблему, нам понадобится пример. Давайте возьмем синтетические сапфиры из «IR 2». Чтобы сделать сапфир, вам понадобится чистый минерал никель, диоксид кремния и сапфировая пыль, однако сапфировая пыль образуется путем дробления сапфиров, образуя цикл:

Способ, которым я решил эту проблему, заключается в том, что при обнаружении петли она разрезается в одной точке, а затем рецепты объединяются в один. Затем для расчета используется новый рецепт вместо того, которым закончилась выпрямленная петля. Здесь два рецепта объединены, удалив три сапфировой пыли посередине, затем мы можем удалить два сапфира, которые одновременно являются ингредиентом и результатом:

В итоге мы получаем рецепт изготовления сапфиров, не затрагивая проблемные детали! Но что происходит, если внутри цыкла есть другие циклы?

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

По умолчанию сырая нефть имеет значение 0,4 (пока мы не будем учитывать воду). Это означает, что рецепт имеет общую ценность 40. Итак, мы знаем, что 25 мазут + 45 дизель+ 55 нефтяной газ должны иметь общую ценность 40, но какая часть этой ценности содержится в каждом продукте? Есть много способов подойти к этому, и решение этой проблемы заняло у меня большую часть времени и вызвало много головной боли. Давайте рассмотрим два самых разных варианта.
Самый простой: просто сделайте так, чтобы каждый результат составлял равную часть от общей стоимости. Это в основном разумно, но не работает, когда вы вводите отходы. Например, в процессе обогащения Kovarex получается 41 U-235 и 2 U-238, алгоритм предполагает, что они оба имеют одинаковое значение, но вы, вероятно, знаете, что U-235 гораздо более ценный. Так что этот подход на самом деле неприменим.
«Лучшее»: просто сделайте так, чтобы каждая часть соответствовала полной стоимости, но отслеживайте побочные продукты, которые вы можете вычесть позже. Например, мазут содержит дизель и нефтяной газ в качестве побочных продуктов при глубокой переработке нефти. Это означает, что смазочный материал также содержит их в качестве побочных продуктов, потому что он сделан только из тяжелой нефти. Если мы хотим сделать экспресс-разделитель, нам, помимо некоторых других ингредиентов, понадобятся смазочные материалы и усовершенствованные схемы. Для усовершенствованных схем требуется дизель, но он есть у нас в качестве побочного продукта смазки, чтобы мы могли его вычесть. Единственный оставшийся побочный продукт — это дизель. Что нам делать с дизелем? Мы, конечно, можем взломать его, чтобы сэкономить еще больше нефти. Но для этого нужно немного воды. Дешевле использовать больше воды или больше нефти? Что ж, на всякий случай рассчитаем оба варианта.
Как видите, этот подход безумно сложен. Есть много крайних случаев и вопросов, на которые нужно ответить. Например, что мне делать с лишними побочными продуктами, если они не нужны другим ингредиентам рецепта? Я попытался реализовать вариант этого подхода и должен сказать, что мне это удалось. На это у меня ушло всего около 100 часов, и мне пришлось исправить около миллиона ошибок. И какая была награда? Что ж, это решение все еще не идеально, хотя очень близко. Я также больше не мог разбираться в собственном коде. Все ломалось каждый раз, когда я пытался что-то поправить. И, что наиболее важно, загрузка мода с помощью vanilla Factorio занимала от 10 секунд до 10 минут. Поскольку я хочу, чтобы мод был совместим со многими другими модами (и было бы неплохо работать с vanilla Factorio), я решил, что это не выход.
Наконец, после долгих размышлений я пришел к алгоритму, который использую сейчас. По сути, это компромисс между двумя описанными выше подходами. Он работает достаточно хорошо и довольно просто. Хотя мне это не так просто объяснить, потому что мне нужно было бы объяснить многие другие особенности алгоритма оценки. Он не очень хорошо оценивает все рецепты с несколькими выводами во всех случаях, но он также не работает в крайних случаях (я надеюсь).
Последние мысли
На этом мы завершаем наше рассмотрение внутренней работы Рандомайзера рецептов. Если у вас есть какие-либо вопросы или предложения, вы можете написать мне на Discord server. Говоря об этом, я хотел бы поблагодарить всех людей, которые присоединились к нему и публиковали ошибки, идеи, тестировали или иным образом поддерживали меня во время разработки. Без вас мод не зашел бы так далеко!
COMFY Сапёр! redlabel
Чтобы отпраздновать новый дизайн карты от легендарного производителя карт mewmew и новый блестящий Ryzen 9 5950X от Gerkiz, COMFY Factorioорганизует специальное мероприятие 1 мая в 17:00 UTC. Приглашаются все и их семьи, нет необходимости отвечать.

Если кому-то интересно, что такое «Сапер», то это новая карта, на которой расширение базы происходит за счет решения загадки «Сапер». Чтобы очистить мину, над ней нужно поставить печь. Размещение его на чистом месте вызовет взрыв, а наступление на него без предварительного очищения приведет к тому же результату. Ошибки дорого обходятся, так как они выпускают злобных кусаr и вызывают ядерные взрывы. Игроки также могут зарабатывать (или терять) очки в зависимости от того, насколько они хороши, и могут сравнивать себя с другими через табло, на котором отслеживаются ценные интернет-очки.
COMFY — одно из ведущих многопользовательских сообществ Factorio, и некоторые из наших творений — Mountain Fortress, Biter Battles, Fish Defense, Chronotrain и Cave Miner. И очень-очень скоро в него войдет карта о пиратах и парусных кораблях! Следите за новостями.
Вы можете присоединиться к сообществу COMFY, насчитывающему почти 3500 участников, на нашем Discord.
Содействие
Как всегда, мы ищем людей, которые хотят внести свой вклад в Alt-F4, будь то отправка статьи или помощь с переводом. Если у вас есть что-то интересное, чем вы хотите в изящной форме поделиться с сообществом, то это место для вас. Если вы не совсем уверены в этом, мы с радостью поможем, обсудив идеи содержания и вопросы структуры. Если это похоже на то, что вас интересует, присоединяйтесь к Discord, чтобы начать!
Comments: