Хабрахабр

Возможно ли загрузить непроходимый уровень в Super Mario Maker?

Данная запись — вольный пересказ видео Is it Possible to Upload an Impossible Level in Super Mario Maker?. В ролике есть отсылка на видео The Impossible Level, поэтому перескажу и его. Мой пересказ не претендует на точность, я просто хочу поделиться интересным материалом.

О чём пойдёт речь

Поиск ошибок в ПО бывает очень разным. Я занимаюсь поиском ошибок в исходных кодах, в бинарных файлах, в больших комплексах программ и даже в каких-то железках. Но есть область, в которой я практически никогда ничем не занимался — поиск ошибок в компьютерных играх.

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

Одной из ключевых особенностей игры стала возможность пользователям самостоятельно создавать уровни (здесь они называются курсы) и делиться ими с другими игроками. В сентябре 2015 года компания Нинтендо выпустила Super Mario Maker — платформер про известного сантехника Марио. Именно в этот момент у игроков-исследователей зачесались руки — а можно ли опубликовать непроходимый уровень? Кто-то уровни создаёт, отслеживает процент успешных прохождений, а кто-то, собственно, проходит эти уровни.

Рисовать что-то такое нет смысла, уровень хоть и действительно непроходимый, но и опубликовать мы его не сможем.
Перед Нинтендо стояла довольно интересная задача — как не допустить «захламления» библиотеки пустыми и непроходимыми уровнями. И они с ней хорошо справились. Решение довольно элегантное и не раз применялось в играх с подобной творческой концепцией: уровень нужно пройти самому перед публикацией и загрузкой на сервер. Причём один раз от начала и по разу от каждого чекпоинта. Фактически, задача сводится к тому, что необходимо разработать курс, который автор сможет пройти во время публикации, но не после неё.

Попытка номер 1. Кодовый замок

В игре множество объектов, которые взаимодействуют друг с другом по известным правилам. Можно попробовать воспроизвести что-то похожее на кодовый замок.

Для примера можно взять такую заготовку:

Купа (1) не может проходить свозь монстров на её пути (3), за исключением привидений (2). Монстры, находясь на головах друг у друга, не разбегаются и стоят на месте. Если Марио ударит кирпичный блок (4), то нижний монстр из стопки умрёт, опустив привидение на один блок ниже. Если привидение будет на одной линии с купой, та сможет пройти дальше. Автор уровня знает количество монстров до каждого привидения, и он знает сколько раз нужно ударить каждый блок, чтобы высвободить путь для купы. Как только купа пройдёт мимо всех монстров, она активирует триггер и освободит проход для Марио.

Игрок не видит монстров, уровень разбит на независимые сегменты, в каждом из которых нужно знать сколько раз и в какой кирпич биться. Этот пример приведён только для наглядности — в реальных попытках сделать кодовый замок все было сложнее. И только точное прохождение всех сегментов открывает проход к выходу с курса.

К сожалению, данный подход имеет ряд существенных минусов:

  • Какой-то задрот энтузиаст может потратить много времени и перебрать всё количественно.
  • Удачливый игрок просто ударит выбранные наугад блоки и, ВНЕЗАПНО, это будут те самые блоки, которые надо ударить то самое количество раз.
  • Игроки могут просто скачать курс и открыть его в редакторе. После изучения, при должном усердии, они узнают «код».

Продолжим поиск способа загрузки непроходимого уровня.

Попытка номер 2. Красные монеты

Пользователь ReflectivistFox опубликовал видео The Impossible Level в котором предложил интересную идею для публикации непроходимого уровня. Правда, есть существенное ограничение: его курс проходим, если играть его с начала и до выхода, и АБСОЛЮТНО-ТОЧНО-ПОЛНОСТЬЮ-СОВСЕМ непроходим, если воспользоваться чекпоинтом. Казалось бы, при таких ограничениях уже не так интересно рассматривать концепцию уровня, но на самом деле даже такой шаг очень важен. Вы ещё помните, что во время загрузки уровня его нужно пройти не только от начала, но и от каждого чекпоинта? ReflectivistFox преодолел половину ограничения — его уровень можно пройти во время загрузки, но нельзя в обычном режиме.

Красными они были в предыдущих играх серии Марио, а розовыми стали в Super Mario Maker. Ключевой идеей является использование игрового элемента «красная монета» (сразу уточню, что игроки называют их и «красными», и «розовыми». В обычных уровнях красные монеты используются как части собираемого ключа. Принцип их работы одинаков, поэтому здесь и далее я буду использовать только «красный»). Как только Марио собирает их все (игрок знает точное количество монет), он получает ключ от специальной двери, за которой могут быть какие-то бонусы или проход дальше по уровню. Автор курса располагает несколько таких монет в труднодоступных местах.

Чекпоинт сохраняет игру, когда Марио активирует его. Важной особенностью является то, что эти на эти монеты по-особенному влияют чекпоинты. Все игровые элементы восстанавливаются: враги, бонусы и прочее. Если игрок проигрывает, персонаж погибает, то происходит загрузка с последнего чекпоинта. Они не восстанавливаются, хотя сохраняется количество собранных монет. Но не красные монеты. Если собрать все красные монеты и проиграть, то поведение меняется — счетчик обнулится, а монеты будут на своих исходных местах. И это не вся особенность.

ReflectivistFox в своём уровне использовал две особенности игры.

Обратите внимание, что чекпоинт (красный флаг в центре) наполовину закрыт блоком. Такая установка создаёт интересный эффект — активировать его можно, добравшись до верхнего блока, а при загрузке игра не сможет создать персонажа внутри блока, и он «выпадет» ниже, возле дверей и динозавра.

На этом маршруте его ждёт следующее: Таким образом, игрок, который загрузится с чекпоинта, попадёт на альтернативный маршрут.

Тут много элементов и коротко очень сложно описать, поэтому я выделю только самые важные вещи.

Для этого ему нужно пройти по стрелочкам влево, подняться наверх и по блокам сверху пройти вправо (на скриншоте путь вверх и вправо проходит совсем по границе, но более удачного кадра не сделать). Марио появляется из двери и его взгляд направлен так же, как на картинке, а добраться ему надо до двери справа (4). Все остальные способы завязаны на том, чтобы дракончик воспользовался блоком POW (3) — он будет отталкиваться и двигаться спиной, что позволит попасть влево без раннего провоцирования группы (1). Специальная конструкция объектов (1) запрещает персонажу поворачиваться, если он это сделает, то пропадёт объект (2), и проход закроет подвижная стенка над ним. Чтобы войти в дверь игроку нужно расположить что-то под дверью, чтобы быть с ней на одной горизонтали. К сожалению, перемещение блока POW (3) делает невозможным использование двери (4). Все варианты, которыми располагает игрок, приведут к взрыву POW или невозможности донести этот блок до двери (4). Игрок может попробовать ловкостью рук забрать блок POW (3) и пронести его до двери, но автор позаботился и об этом — вертикальная часть маршрута слишком высока, чтобы ее можно было преодолеть обычным прыжком. А как же сам автор прошёл его при публикации? Именно с такой неразрешимой ситуаций сталкивается игрок, который решит пройти этот уровень от чекпоинта.

Изначально на этом месте находится красная монета. Обратите внимание на блок (пустой), который я отметил цифрой 5. Во время проверки игра не может определить, какие красные монеты игрок собрал, поэтому она, загружая состояние игры в чекпоинте, восстанавливает все красные монеты, давая возможность зазевавшемуся игроку собрать их все, если требуется. Во время прохождения, до чекпоинта, игрок не может пройти мимо и обязательно заберёт эту монету, и именно поэтому в данном месте сейчас пусто. А во время публикации, она там будет гарантированно — что позволяет воспользоваться ей вместо блока POW (3) для движения влево и спокойно выйти в дверь (4). Вторая красная монета вмурована в стену и её невозможно собрать, тем самым обеспечивается невозможность перезагрузить счётчик монет, и поэтому во время игры на месте блока (5) монеты не будет, когда она будет нужна. А там уже и выход с курса рядом.

Итог этой попытки:

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

Не унываем, продолжаем и ищем.

Попытка номер 3. Странный гриб

Разница была найдена! Это, так называемый, «странный гриб». С вероятностью в 1% странный гриб появляется вместо обычного.

Вот так выглядит странный гриб.

А вот Марио после, хм… использования гриба. Странный Марио отличается от обычного существенно более высокими и дальними прыжками. Кроме того, если Марио съест сначала обычный гриб, а потом странный, то Марио станет странным. Если поступить наоборот, то он всё равно останется странным — обычный гриб не окажет никакого эффекта.

Если бы все было так просто, то любой мог бы создать уровень вроде такого:

Длина рва специально рассчитана так, что обычный Марио его не перепрыгнет, а странный — легко. Достаточно переигрывать его раз за разом, пока не выпадет странный гриб. К сожалению, данный способ нам не подходит, так как он даёт целый 1% для вероятности прохождения. К счастью, Нинтендо уровень тоже не устраивает из-за того, что в 99% он непроходим и они решили исправить такую ситуацию. Во время публикации странные грибы не будут появляться никогда.

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

Вот так может выглядеть целая “грибная ферма”, которая принудит Марио собрать около 200 грибов (ограничение в 100 блоков одного типа, но можно разместить 100 в основном мире и ещё 100 в дополнительном).

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

Собираем вместе и подводим итог:

  • Очень хорошая попытка, которая с просто огромной вероятностью не даст пройти игру в обычном режиме.
  • И все-таки есть вероятность в 13,4% (0,99^200 ~ 0,134, если мы считаем, что все генерируется с равномерной вероятностью), что странный гриб не выпадет, и уровень будет все-таки пройден. А даже если и не равномерно, то вероятность все равно есть, и уровень потенциально всё же может быть пройден.

Что же делать? Последний шанс.

Попытка номер 4. Блоки с двойной сущностью

Вы помните первую картинку к этой статье? Я повторю её:

Этот уровень был реально опубликован среди прочих уровней. И может быть опубликован ещё.

Когда игра только вышла, в ней были баги. Нинтендо хорошо постаралась, когда придумывала логику проверки уровней, но так было не всегда. И если мы воспользуемся одним из них, то сможем выполнить задуманное.

0. Сначала надо сделать вайп всех данных на Wii U и установить Super Mario Maker v1. И можно будет играть в игру, какой она была на момент старта. Делать это надо в режиме офлайн, чтобы игра не обновилась.

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

Накладываем на облачко сплошной блок с маршрутом.

Спустя некоторое время Нинтендо запатчили это, чем поломали все уровни, которые использовали этот баг, потому что починка фактически из двойных блоков оставила только наложенные. Такие блоки схлопнутся и будут вести себя как изначальный блок, а выглядеть — как наложенный.

Блоки (1) только выглядят сплошными, а логически это обычные монетки.

Точнее попробовать стоит — игра предложит пройти наш курс, что мы легко сделаем. После того, как такой уровень создан, не обязательно публиковать его сразу. Но всё равно уровень будет помечен как пройденный и отправится на сервера без дополнительных проверок. А вот отправить его на сервера не удастся, мы же не включили интернет. В которой курс уже невозможно пройти. Даже после обновления игры до актуальной версии.

Вот он — загруженный и абсолютно точно никак и ни при каких обстоятельствах не проходимый уровень. Готово! На этом и завершается наше небольшое путешествие в мир исследования игры Super Mario Maker. С четвертой попытки успех был достигнут.

Заключение

Спасибо, что дочитали эту простыню текста с картинками. Я постарался доступно рассказать о процессе поиска ошибок в логике работы приложения. В данном случае — это игра, но общие подходы сохраняются, если их переносить на системное и прикладное ПО. Код может быть написан хорошо, но это не означает, что и работать все будет так, как задумано. Логические уязвимости очень опасны и сложнообнаружимы, но этим и интересны.

Всем хороших игр, уязвимостей и добра!

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть