Форс первый, Sword Girls

Published
Если вдруг так вышло, что кто-то отказался читать заголовок, то да, сегодня я твёрдо намерен зафорсить вам, дорогие камрады, нечто, вообще говоря, вполне обыденное.
Это всего-то навсего корейская онлайновая коллекционная карточная игра с няшками на картах.

Столкновение

Наткнулся я на неё, мэшая f5 на первой странице форчана (занятие, достойное истинного джентльмена!).
Там, некий мутный анон вопрошал что-то вроде "Why aren't you building a maid deck yet?".
Пораскинув остатками вычислительных центров, я зашёл в тред, посмотрел немного скриншотов, отписался про Уламога (в любых тредах о карточных играх всегда есть место обсуждению про Уламога), но так и не нашёл ответа на вопрос из первого поста.
Пришлось слабануться и загуглить игру. Английская версия тогда была на стадии "закрытой" беты, то есть вы вводите любой почтовый адрес и вам немедленно отправляют код, впрочем почему-то всегда один и тот же, да и вообще вводить его, как оказалось, не надо было - при успешной проверке (представляю себе этот феерически сложный алгоритм. if ($_GET['code']=='BETA21337'){...}) пользователя просто-напросто редиректило на другой адрес, без каких-либо потайных хидеров и прочей шелухи.
А и правда, зачем?
Я, по правде говоря, с подозрением отнёсся тогда к игре с таким глубокомысленным названием и такой надёжной политикой набора тестеров, но, как оказалось, ленивыми идиотами были не авторы игры, а локализаторы - корейская версия содержит поразительно низкое для браузерной игры количество фатальных дыр в обороне.

Игра

Покончив с регистрацией, я принял мудрое решение проследовать мимо форумов сразу к кнопке Play now.
Там мне предложили выбрать одну из четырёх фракций.
При этом про каждую из них сообщалась пара строчек скорее сюжетной информации и никаких намёков но то, что, собственно, от моего выбора зависит. Вместо этого давались изображения "лидеров фракций". В списке имелись:
  • классического вида леди, именуемая не иначе как Beautiful and Smart Cinia Pacifica
  • крайне молодо выглядящая девица с мечом, какой-то непонятной цепью и полным отсутствием эмоций на лице
  • не слишком-то хорошо прорисованная дама с грудью, занимающей солидную часть арта и типичным моралфажеским фейсом
  • девушка на фоне лилий, с виду нормальная, за исключением повязки на глазу
После продолжительных размышлений и мысленно извинился перед местным клоном реи и ткнул в стрёмную девицу с повязкой (на картинке слева).
Лилии, в конце концов, должны что-то символизировать, не так ли?
Как оказалось впоследствии, первая фракция содержит "леди и горнишных", вторая - обычных японских школьниц, третья - местных рыцарей, а четвёртая, извините, всякую нечисть вроде, гм, вампиров. Выбор фракции влиял только на предоставляемый стартер, но функции перевыбора не было, а создавать новый аккаунт (и проходить заново мучительную процедуру отбора тестеров) ради колоды на горнишных было влом, и я остался копаться в вампирчиках. В конце концов, лидер фракции у них действительно ничего.
Что до лилий, то да, в игре полностью отсутствуют персонажи мужского пола, в результате чего романтические сюжетные линии принимают захватывающие обороты, и тащемта не все карты в игре SFW.
(справа: "А как, по-твоему, должны вылядеть мои вампирические ритуалы?")
Ах да, я же хотел в этом разделе напечатать что-нибудь про геймплей.
Он, кстати, внезапно затягивает, играть можно не только ради няшек.
Вообще в главном меню игры можно увидеть пункты Dungeon, Fight, Shop, Lab, Deck и Arena.
Назначение большинства кнопок вполне очевидно.
Почти на каждой карте где-нибудь да присутствует слово "random", в результате чего вполне реально собрать миллионы колод, практически не требующих применения мозга. Как следствие, бои с ботами не обязательно скучны, и Dungeon (в котором этих данжей, кстати, десятки) служит для планомерного гринда бесконечных материалов, которые используются для крафта новых карт.
Как-то так. Вообще пункт Lab содержит функции карфтинга карт, трансмутации некоторых реагентов, сжигания ненужных карт с разбором их на базовые материалы (и невероятными потерями)... А ещё там можно тренировать карты и повышать им уровни. Да-да.
(не совсем ясно, почему большую часть экрана занимает некое подобие рекламного щита, ну да ладно)
Cам игровой процесс примерно такой:
  • в начале каждого хода каждый игрок добирает из колоды карты до 5. Если в руке уже есть 5 карт, самая левая сбрасывается, после чего берётся одна карта.
  • после этого у игрока есть 30 секунд на то, чтобы разыграть до 5 карт. На поле попросту имеется 5 слотов.
  • в углу каждой карты присутствует цифра в кружочке. Это размер. Суммарный размер всех карт на поле одного игрока не должен превышать 10.
  • кнопка shuffle делает вот что: карты, находящиеся в вашей руке, отправляются вниз колоды, после чего вы берёте столько же карт. Да-да, самого шаффла не происходит ┐( ̄ー ̄)┌
  • при этом можно в режиме реального времени видеть, как оппонент разыгрывает карты, однако они показаны рубашкой кверху, так что определить можно только количество разыгрываемых карт.
  • по истечении 30 секунд (или при нажатии снопки ready) карты резко переворачиваются лицевой стороной кверху и подбрасывается монета
  • собственно, карты делятся на два типа: заклинания и существа (хотя здесь это называется follower)
  • сначала срабатывает случайная карта на поле игрока, выйгравшего подброс монеты. При этом, впрочем, приоретет отдаётся заклинаниям.
  • когда приходит черёд существа делать своё грязное дело, оно случайным образом атакует какое-нибудь существо на поле оппонента, нанося ему повреждения, равные своей атаке. Если существ у оппонента нет - урон наносится персонажу оппонента, но в этом случае он равен размеру атакующего существа. После атаки существо деактивируется и ничего не делает до следующего хода
  • когда какое-либо существо пробивает по другому существу, то всегда наносит ответный удар (если, конечно, остаётся в живых).
  • когда у существа остаётся 0 и меньше выносливости, оно отправляется на кладбище и наносит персонажу контролирующего его игрока урон, равный размеру погибшего существа. Сформулировал я как-то магически, но на самом деле это работает крайне просто.
  • когда у персонажа становится 0 или меньше здоровья или если в начале хода у игрока в колоде не осталось карт, этот игрок проигрывает
У существ часто имеются стрёмные способности, которые могут внезапно приводить к неожиданным результатам.
А знаете, что ещё имеется у существ? Феерические арты, вот что у них ещё имеется.
Но нет, я не стану отвлекаться на подробное описание сюжетных похождений одного и моих любимых персонажей (У НЕЁ ШАРФИК НАДЕТ ПОВЕРХ БИТЫ О БОЖЕ)
Лучше перейти к захватывающей части повествования - о взломах, ботах, переводах и прочих чудесах современных интернетов.

Корея

Через несколько дней после окончания закрытой беты я ощутил лёгкий withdrawal syndrome и отправился на поиски оригинала.
И оригинал нашёлся, хотя и был заметно менее японским, чем я ожидал. Ну что ж, я пожал плечами и полез регистрироваться в корейской версии, благо гугл хром позволяет вытворять и не такие трюки.
На первой же странице меня поставило в тупик поле "Ваш номер социальной страховки", как бы невзначай стоящее рядом с именем и фамилией.
Попытка вбить рандомную последовательность цифр вызвала мгновенную негативную реакцию. Почуяв жабоскрипт (скорость возникновения окна с ошибкой была слишком высока), я воззвал к исходному коду страницы и вскоре нашёл функцию проверки номера страховки.
Надо сказать, функция эта написана самым невероятно быдлокодерским способом из возможных. Я слегка оптимизировал её, введя в консоль что-то вроде function check() {return true;}.
Теперь при нажатии кнопки страница незамедлительно начала прогружаться и я уже было издал ликующий вопль, как вдруг передо мной возникла красная надпись "ваш номер страховки не совпадает в вашим именем".
Это, надо сказать, поставило меня в тупик. Как же так? Откуда какая-то левая контора по производству браузерных игр получила базу данных номеров соц.страховки?
И, в конце концов, если у них есть доступ, он должен быть и у меня! С этими рызмышлениями я полез гуглить формат номеров страховки в корее.
Формат, надо сказать, довольно любопытный. Первые 6 символов являют собой дату рождения, а в последующих закодировано место рождения и которым по счёту ребёнком вы были в тот день в этом месте.
Последняя цифра являет собой слишком, слишком сложно полученный хеш предыдущих.
Так или иначе, по ходу изучения формата я нашёл несколько примеров реальных номеров с именами и прочей информацией, и первая страница осталась позади.
Однако фан и не думал завершаться! Дальше с меня спрашивали адрес. И не как нибудь, а "начните вводить ваш домашний адрес".
Следом за полем шло выпадающее меню, содержащее печальное "ничего не найдено".
После нескольких бесплодных попыток обойти эту форму путём жабаскриптовых манипуляций (что крашило скрипт регистрации), я вновь воспользовался поисковыми системами и обнаружил, что адреса в корее принято начинать с города.
Следующий мой поисковый запрос был вполне очевиден - "cities in korea wiki".
("Что я говорил о лилиях?")
Внизу страницы запрашивались сразу три номера телефона (и все - обязательны к заполнению), но они, к счастью, никак не проверялись.
Наконец, мне предложили выбрать фракцию. Я к тому моменту уже успел выработать фагготрию по отношению к Айри Флине и не задумываясь ткнул всё в тех же вампирчегов.
О, как прекасна была корейская версия! В десятки раз больше карт, фич, персонажей, акций!
Карты, разрушающие мозг своей прелестностью!
Бесконечные потоки очень плохих корейских игроков, служивших отличным способом набрать реагентов!
Единственная проблема была очевидна - я не знал корейского.
Впрочем, корейская письменность оказалась не в пример проще японской - хангул, оказывается, ограничивается звукописью, причём и там всё максимально просто и логично. Но без знания грамматики и словаря я мог только распознавать ключевые слова вроде "выносливость" или "айри".
Со временем торчать среди игроков, с которыми невозможно поговорить, мне немного наскучило и я отважился заглянуть в американские форумы. Они, конечно, были ужасны, но там был дан адрес IRC-канала по игре, где я нашёл массу интересных личностей.
Например, человека, который перевёл все карты.

IRC

Собственно, я впервые зашёл в канал #swordgirls @ irc.rizon.net как раз когда феерический аутист под ником Hikki заканчивал работу над переводами.
Повосхищавшись немного его работе, я предложил запилить в чатик бота, который бы выдавал информацию по заданному имени карты.
Тут же всплыл один из юзеров, который приспособил имевшегося в наличии бота для Magic: The Gathering.
Подкорректированной версии, по вполне понятным причинам, нужны были отдельные команды для артов и текстов.
И вот тогда я подумал, "а было бы здорово, если бы какая-нибудь тулза могла выдавать эти переводы прямо по ходу игры".
Затем я подумал ещё немного, но в итоге так и не смог измыслить ничего лучше, чем сделать её самому.
And the Great Work began...
Здесь надо отметить, что при наведении мыши на карту, вне зависимости от расположения, в правой части экрана высвечивается чуть более крупно арт этой карты и описание её способностей.
Быстро отказавшись от идеи проникнуть в память флэш-игры, я решил исходить из скриншотов, снимаемых тулзой каждые н секунд.
Поначалу я копался в распознавателях текста, но выдаваемые OCR результаты были насколько далеки от истины, что ни о каком поиске не могло быть и речи.
Оставалось одно - распознавать изображения.
Но где взять базу? Картинки на оффсайте были либо слишком большими, либо слишком маленькими и их было трудновато сравнить с теми, что высвечивались в игре. В самом деле, сложно добиться абсолютно аналогичного ресайза.
Однако чуть позже я совершенно случайно узнал, что "маленькие" картинки в базе карт на официальном корейском сайте на самом деле имеют разрешение того самого внутриигрового предпросмотра. Запилив наспех хеш-алгоритм и запустив несколько скриптов, я с ужасом осознал, что тулза полностью операбельна.
Да-да, на тех игровых скриншотах, что я постил выше, просто не видно висящей рядом с клиентом программы.
Чуть позже к проге были добавлены всякие лишние фичи и кнопки вроде обновления баз данных, поиска карт, и прочая и прочая.
Пришло время ещё одного арта с изображением девочки с битой!

Махинации невозможно остановить

Некоторые карты в игре крафтятся из карт, которые крафтятся из карт, которые крафтятся из карт.
В результате вычисление количества требуемых базовых реагентов превращается в трудновыполнимую задачу.
Итак, новой целью нашей небольшой команды из 2.5 излишне увлёкшихся идиотов стало создание базы данных крафтинга.
Сначала было принято решение не трогать всякие там исходники, и я накодил ужасное порождение зла, которое шевелило моей мышкой, прокликало все карты в меню крафтинга и считало с экрана все списки реагентов.
Тут, конечно, было сразу несколько проблем:
  • распознавание картинок работало далеко не идеально, некоторые карты имели одинаковые арты
  • процесс вышел крайне нестабильным и продолжительным, мне пришлось больше часа следить за работой скрипта
  • к игре довольно часто выпускаются дополнения (которые здесь грамотно называются эпизодами), и проводить каждый раз этот богомерзкий ритуал мне не хотелось
В итоге я вздохнул и полез декомпилировать код игры.
Надо признать, что actionscript не был обфусцирован совсем (это первый из тех крайне немногочисленных провалов защиты, о которых я говорил выше), но, тем не менее выглядел невероятно громоздким.
Торжество объектно-ориентированного программирования во все поля, кто-то явно привлёк к разработке программистов, специализирующихся на Java.
Хотя, возможно, это всего лишь последствия декомпиляции.
Просидев над феерией полдня, я выяснил следующее: то, что в игре называлось crafting, в коде называется upgrade, а upgrade носит название enchant. Причины таких манипуляций остаются для меня загадкой до сих пор, но я отлично помню своё негодование, когда я обнаружил таки единственную на всю программу точку соприкосновения этих понятий.
Сам протокол оказался достаточно простым, и я быстро набросал скрипт на ruby, который выполнил необходимые запросы за несколько минут и выдал чистый список.
Пару дней мы просто дивились на этот чудо-скрипт, после чего основали свой чатик с неприлично завышенными уровнями паранойи на входе, где начали обсуждать возможные дальшейшие перспективы.
По ходу дела я не удержался и организовал бота, который нафармил мне немного реагентов и послужил причиной моего бана на 2 недели.
Я даже удивился тогда оперативности админов игры.
В протоколе, вообще-то, есть одна проблема, делающая подобных ботов довольно опасными - смена фаз во время хода вызывается командами со стороны клиента. То есть если при реальной игре вы сидите и смотрите, как карты обмениваются ударами, то бот просто пропускает все анимации и мгновенно переходит к следующему ходу, что ускоряет прохождение и набор реагентов в десятки раз.
Забавно, кстати, что некоторые списки реагентов не помогают крафту совсем.
Взять, например, карту Edelfelt of the Wing.
Прежде чем скопипастить необходимые для крафта материалы, сообщу, что на прохождение одного этажа данжа уходит несколько минут, и даётся за это по 1-2 штуки четырёх разных материалов
23:14 < nvm> $$edelfelt of the wing
23:14 <+swogi> Base Recipe for Edelfelt of the Wing - 1506x Sword, 2752x Glasses,
3266x Shoes, 2852x Socks, 2556x Ribbon, 5644x Cat Doll, 3680x Book,
4134x Red Ore, 4134x Green Ore, 4134x Blue Ore, 4134x Black Ore, 544x
Ruins Fragment, 1248x Heart Stone, 1536x Holy Water Tear, 1696x Bamboo,
1536x Lily, 1464x Good Job Stamp, 2192x Spiral Fragment, 130x Talentium
Marble, 824x Dagger, 896x Panda Doll, 768x Trump, 832x Gloves, 824x
Perfume, 832x Lipstick, 816x Pendant, 2368x Naturalist's Brick
Да-да. Тысячи. Именно так, да. И да, я видел игроков с этой картой, и не раз.
(edelfelt of the win смотрит на тебя как на корейского фармера)
Совсем недавно мы решили возобновить работу над некоторыми проектами (автоматизировать, чёрт побери, обновления, чтобы больше не пришлось делать этого вручную) и обнаружили, что скрипты работают как-то странно - у меня не лоинились вообще, у некоторых срабатывали, но быстро вылетали.
Наконец мы поняли, что скрипты работают только тогда, когда где-то запущен настоящий клиент игры. Причём неважно где. Более того, при этом в качестве пароля можно вводить абсолютно всё, что угодно.
На самом деле клиент игры соединяется сразу с несколькими серверами - первый и основной, login server, служит для... ну... логина, а так же чата и некоторых других фич. market server обрабатывает манипуляции с картами, вроде карфтинга, а назначение battle server вполне очевидно.
Так вот, в каждый сервер логин происходит отдельно, но только после успешного соединения с сервером логина.
Почти сразу после возникновения этих сбоев в раблоте скриптов стало ясно, что подключение к серверу логина почему-то больше не срабатывает.
Однако, как оказалось, оно и не было необходимо - можно смело подключаться к маркет-серверу напрямую, используя логин любого онлайнового игрока и любой бред в качестве пароля.
Напоминаю, что одной из функций Lab (а, значит, маркет-сервера) является уничтожение ненужных карт за крохотную долю реагентов.
Таким образом, злонамеренный трюкач может превратить вышеописанную эдельфельт в горстку базовых реагентов, добываемую за одно прохождение первого этажа самого легкого данжа.
Судя по отсутствию прецедентов на форумах, до нас этого никто не обнаруживал, ну и ладно.
Как раз сегодня мне удалось исправить схему логина (оказывается, теперь помимо логина и пароля отправляется идентификатор локализации), и все скрипты вернулись в строй.
А кстати мы внезапно подошли к концу сегодняшнего рассказа и сегодняшнего форса.
"I'm not letting you sleep tonight~"


Views: 2 928

Doc #1 - 10 years ago 0
Голосов: +0 / -0
Классно в целом.
По правилам игры очень похоже на древнюю флешку(Card Master) или что-то такое.
HGL #2 - 10 years ago 0
Голосов: +0 / -0
А кстати забыл написать, открытый бета-тест на английском начинается 28 марта.
И ещё, гугл транслейт обращает блогпост в собрание фантастических фраз.
Doc #3 - 10 years ago 0
Голосов: +0 / -0
Вообще очень классно пишешь, даешь еще. Подписался.
Uber #4 - 10 years ago 0
Голосов: +0 / -0
В общем, да, думаю, тоже подпишусь на различную виабушную ерунду. Но хотелось бы форсы не только на игры, но и другие продукты.