Pull to refresh

Простой бот для игры «Bejeweled Blitz» на C++ и Qt

Reading time 6 min
Views 14K
В последнее время появилось много статей про написание ботов для flash игр. Хочу поделиться своим опытом написания бота для Google+ игры «Bejeweled Blitz».

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

Кроме того, в боте есть «полу-честный» режим, когда на игровое поле выводятся только подсказки хода, а непосредственно ход игрок должен выполнить самостоятельно.

Несмотря на то, что бот написан на мультиплатформенной библиотеке Qt, он содержит немного платформозависимого кода для Windows.

Полный исходный текст бота прилагается.

Немного про игру


Суть классической игры «Bejeweled» заключается в том, что на игровом поле 8x8 клеток в случайном порядке расположены кристаллы семи цветов разной формы.

image

Задача игрока — менять местами соседние кристаллы таким образом, чтобы после перемещения получился ряд из трёх или более кристаллов одного цвета. Если ряд кристаллов не образуется, то перемещения не происходит.

Если образовался ряд из трёх (или более) кристаллов в результате действий игрока, либо
случайно при заполнении поля, то ряд одноцветных кристаллов исчезает, и на его место сверху высыпаются новые кристаллы.

В игре «Bejeweled Blitz» всё то же самое, только на игру отводится одна минута, за которую нужно набрать как можно больше очков.

В игре есть три вида бонусов: «огненные» кристаллы, «ледяные» кристаллы и «универсальные» кристаллы. Бонусы даются за выстраивание более трёх цветов в ряд или за выстраивания разных фигур из одного цвета не лежащих в одном ряду. Бонусы при срабатывании взрываются, либо другим способом уничтожают часть кристаллов на поле.

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


Определение окна с игрой


Используется способ «перетяни мышкой мишень на нужное окно»: для указания боту окна с игрой нужно нажать на мишень и, не отпуская кнопку мышки потянуть курсор в область окна с игрой, затем отпустить кнопку. Для удобства боту можно включить режим «Stay on top», чтобы окно оставалось всегда поверх остальных окон.
В процессе перемещения курсора мышки с мишенью в окне бота выводится название класса окна для контроля.

Вычисление положения игры в окне


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

Перехват игрового поля


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

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

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

Реализация поиска правильных ходов


Поиск правильного хода реализован через паттерны положений.
Существует конечное число расположений кристаллов на поле – паттернов, а именно 16:

image

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

Выполнение хода


Итак, Solver нам нашёл координаты для замены. Теперь нужно последовательно нажать на поле с этими координатами мышкой.
Координаты ячеек массива пересчитываются в экранные, затем, если включен режим «Auto play», дважды вызывается метод, который посылает окну с игрой сообщение о нажатии мышки сначала на одном, а затем на другом кристалле.
При этом окно с игрой не обязательно должно быть в фокусе. Мышка тоже не блокируется, поэтому для пущего удовольствия можно помогать боту, делая ходы собственноручно.
Если включен режим «Show helper», то на игровом поле будут показываться небольшие красные полоски между полями, которые соответствуют правильному ходу. Такая своеобразная подсказка человеку-игроку, какие кристаллы можно менять.

Что можно улучшить


Первое, что хочется сделать, это убрать необходимость подгонки координат, чтобы найти игру на экране. Наиболее простой способ — использовать WebKit часть библиотеки Qt. Мы получаем практически полный контроль над веб-страницей, знаем точное положение всех элементов. Останется только указать смещение для игрового поля внутри игры.
Автоматически мы получаем кроссплатформенность, так как не нужно будет эмулировать нажатия мышки и искать handle окна.

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

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

Как запустить


Запустите бота и включите кнопку «Stay on top», чтобы окно бота было всегда видно. Затем запустите игру в браузере. Окно браузера я рекомендую распахнуть на весь экран, чтобы постоянно не подгонять смещения.
Когда игра загрузится, выключите флажок «Auto play» и включите флажок «Show» в области «Mini field». Далее перетяните мишень из строки «Window class», удерживая левую кнопку мышки, на окно с игрой и отпустите кнопку мышки. Нажмите кнопку «Start/stop», затем начните игру в браузере.
Установите необходимые значения смещения в строке «Game client offset» так, чтобы игровое поле целиком помещалось в окно предпросмотра бота. При правильных значениях смещений индикатор около значений смещений загорается зелёным.
Включите флажок «Auto play», при этом бот должен начать делать ходы.

Примерный вид правильной настройки изображён на скриншоте:

image

Можно подгонять смещения и при включённом флажке «Auto play», тогда бот начнёт играть при совпадении координат автоматически.
Когда бот уверенно заиграет, можно выключить режим просмотра поля в боте, чтобы немного ускорить выполнение.
Включение и выключение бота повешено на глобальную горячую клавишу Alt+A. Флажок «Show helper» включает режим подсказки хода – красная линия между клетками.
В поле «Timeout (ms)» можно изменять время в миллисекундах между срабатываниями таймера (когда выключен режим автоматической игры). Эксперименты показали, что наилучшие результаты получаются в диапазоне 100-200 миллисекунд. Слишком маленькие значения увеличивают ложные срабатывания бота, когда кристаллы падают.
Протестировав бота на разных браузерах, которые у меня есть, я обнаружил странную особенность IE9: при правильной настройке смещений по зелёному индикатору бот не работает. Нужно уменьшить смещение X на единицу, тогда бот срабатывает правильно. С чем это связано я ещё не разобрался. Если у вас такое проявляется – настраивайте бот с включенным флажком «Auto play», не обращая внимания на показания индикатора.

Видео-демонстрация игры бота





Информация о программе


Программа полностью автономна, не производит никакую запись в реестр.
Программа записывает свои настройки в текстовый файл «settings.conf» в папке, из которой была запущена, поэтому для правильной работы настроек требует наличия прав на запись в свою папку.

Внимание! Как известно, можно легко накликать беду, если кликать не туда. Программа бота занимается тем, что много кликает кнопкой мышки, поэтому будьте внимательны при указании боту окна с игрой, лучше на всякий случай перед запуском бота закройте важные документы или закладки браузера с другими важными сайтами или данными.
Убедитесь, что если бот начнёт отчаянно кликать мышкой куда-то в другое окно, у вас не произойдёт непредвиденной ситуации.

Автор не несёт никакой ответственности за возможный причинённый моральный или материальный ущерб.

Бот скомпилирован с библиотекой Qt 4.7.3 компилятором MinGW.

Скачать


Исходники: на github, в архиве: bejeweled_bot_src.zip.
Скомпилированный бот для Windows (полный комплект): bejeweled_bot_complete.zip.
Только exe: bejeweled_bot_exe_only.zip.
Только библиотеки Qt4.7.3+MinGW Runtime: qt_mingw_runtime.zip.
Tags:
Hubs:
+24
Comments 24
Comments Comments 24

Articles