Содержание статьи
Рассказывать подробно о самой игре не буду, о ней слышали, наверное, даже те, у кого нет мобильного телефона. Начнем сразу с интересного.
warning
Редакция не рекомендует рассматривать Hamster Kombat как потенциальный источник заработка: почему — есть подробная статья на «Хабрахабре». Мы будем подразумевать, что имеем дело с обычной игрой, и используем ее как популярный пример, на котором можно продемонстрировать техники автоматизации.
Задача
Игра запускается через бота в Telegram, смысл заключается в наращивании пассивного дохода с биржи. Увеличивать доход можно с помощью покупки карточек, каждая карточка дает определенную прибавку к доходу. Деньги для покупки карточек добываются двумя путями: из того самого пассивного дохода и нажиманием большой кнопки в центре экрана.
В процессе игры у меня быстро появилось желание автоматизировать две вещи: нажатие на кнопку и выбор оптимальных карточек для покупки. У каждой карточки две основные характеристики: размер прибавки к доходу и цена. Одни карточки дают небольшую прибавку и дорого стоят, другие, наоборот, очень выгодны. Для простоты анализа я ввел понятие удельного дохода, ну или его еще можно назвать «цена прибавки». Допустим, если карточка стоит миллион монет и дает прибавку к доходу 4000 монет, значит, цена прибавки будет 1 000 000 / 4000 = 250 монет. Чем меньше цена прибавки, тем целесообразнее покупка монеты.
Характеристики карточки меняются после каждой покупки, поэтому на глаз все проанализировать и выбрать наиболее выгодную карточку по цене прибавки практически нереально. Для начала я составил табличку, добавил в нее все карточки и отсортировал их по удельной доходности (цена/добавка). Все бы хорошо, но это не отменяет необходимости после каждой покупки вручную обновлять изменившиеся характеристики карточки. Что ж, попробуем автоматизировать.
С ходу в голову пришел очевидный способ взаимодействия с игрой — анализ изображения на экране и эмуляция нажатий на экран с использованием Android Debug Bridge (ADB). Конечно, в идеале бы все сделать на запросах, вообще без телефона, но для этого надо анализировать трафик, а с учетом того, что игра запускается только на телефоне, внутри Telegram, анализ трафика мне показался весьма трудоемкой задачей, поэтому я решил начать с более очевидной реализации.
Автоматизация через ADB
Тапаем на экран
Надеюсь, что устанавливать ADB и взаимодействовать через него с телефоном все умеют, поэтому не буду лить воду про это, перейдем сразу к делу. Попытки запустить игру в Windows закончились неудачей, поскольку игра каким‑то образом определяет, что запущена не на телефоне, и выводит сообщение об этом. Что ж, телефон — значит, телефон. Вооружаемся телефоном с Android, расчехляем ADB. Вопрос с тапаньем по кнопке легко решается одной командой:
e:\Android\sdk\platform-tools\adb.exe shell input tap 540 1800
540 и 1800 — это координаты точки на экране, в которую мы хотим «ткнуть пальцем». Чтобы не возвращаться к этому второй раз, сразу хочу сказать про так называемую морзянку. В игре каждый день есть возможность получить дополнительный миллион монет, введя с помощью азбуки Морзе определенный код. Точка кодируется коротким нажатием, тире — длинным. Делать короткое нажатие мы уже умеем, длинное же делается вот такой командой:
e:\Android\sdk\platform-tools\adb.exe shell input swipe 500 1500 500 1500 555
Первые четыре числа — координаты начала и конца движения, а 555 — время движения. В нашем случае начало и конец совпадают.
Чтобы минимизировать ручную работу, можно написать на Python скрипт, который будет принимать на вход слово, перекодировать его в последовательность точек и тире и через нажатия вводить в игру. Приведу основные функции, которые понадобятся.
Функция, которая эмулирует ввод точки:
def tochka(): cmd = "adb.exe shell input tap 500 1500" process = subprocess.Popen(cmd, stdout=subprocess.PIPE, creationflags=0x08000000) process.wait()
Функция, эмулирующая ввод тире:
def tire(): cmd = "adb.exe shell input swipe 500 1500 500 1500 500" process = subprocess.Popen(cmd, stdout=subprocess.PIPE, creationflags=0x08000000) process.wait()
Функция, которая разбирает последовательность точек и тире и отправляет ее в телефон (пробел означает паузу в три секунды, необходимую для отделения букв друг от друга):
def mz2tap(morze): for simvol in morze: match simvol: case ".": tochka() case "-": tire() case " ": time.sleep(3)
Перевода текста в азбуку Морзе касаться не буду, не ради этого мы тут собрались. Пример использования:
mz2tap(".--")mz2tap(".")mz2tap("-...")mz2tap("...--")
С первой задачей по автоматизации тапов разобрались, теперь самое время заняться анализом карточек, чтобы выбирать лучшую.
Распознаём карточки
С карточками пришлось повозиться. К задаче я решил подойти в лоб — пролистывать карточки и делать скриншоты, затем обрезать лишнее и распознавать то, что осталось.
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее