Игровые боты. Начало
Что может быть интереснее процесса игры в игры? Правильно! Процесс наблюдения за тем, как играет в игры написанный тобой бот.
Некоторое время, я размышлял, о чём бы написать свою первую статейку. Хотел написать о программировании микроконтроллеров, но оказалось трудно отделить части рабочих проектов от тех, что можно опубликовать без оглядки на коллег. Остановился на идее о ботах.
Введение
Боты для онлайн игр я бы грубо разделил на 3 разновидности по способам реализации:
1. Боты не использующие приложение игры. Имитирующие протокол обмена с сервером.
2. Боты работающие с процессом приложения игры. В случае с Web, работающие с окном браузера.
3. Боты работающие со скриншотом и имитирующие устройства ввода мышь и клавиатуру.
Первая разновидность скорее гипотетическая, т.к. протоколы, как правило, закрыты и не тривиальны.
Первая разновидность больше подходит для ботов с простыми и текстовыми протоколами. Если на сервер передаются бинарные данные, то предстоит разобраться с их структурой, что усложняет задачу.
Вторая разновидность более реальна и может быть реализована. Бот второго вида получает полезную информацию из памяти процесса игры. Недостаток — версии клиентов могут регулярно обновляться и тогда может потребоваться заново искать интересующие адреса памяти.
Мы рассмотрим третюю разновидность ботов, т.к. ИМХО они более привлекательны, хоть и не лишены недостатков.
А так же, такой подход более спортивный 🙂
В этой статье я рассмотрю набор инструментов для самого простого бота для Windows.
Для самого простого бота достаточно эмитировать события мыши и клавиатуры. В большинстве случаев этого оказывается достаточно для решения (не самого эффективного, но не требующего участия человека) рутинных дел в различных играх. Для более эффективной работы бота требуется обратная связь с игрой, т.е. получение и обработка скриншотов игры.
Для разработки приложений я буду использовать Qt Creator + Qt 5 либы (так мне привычнее) и раз бот для Виндовс то + windows.h (WinAPI).
Регистрация горячих кнопок для управления ботом:
Обработка событий нажатия кнопок управления ботом:
Перемещение указателя мыши к нужной точке:
(выполнено не очень аккуратно, обещаю исправиться :-))
Мануал юзера
Перед запуском бота горячей кнопкой Alt-F1, бот следует сначала настроить, определив верные координаты органов управления по которым бот будет кликать.
Для запоминания координат точки наводим указатель месту и жмём Alt-F4.
Для проверки корректности точки отводим указатель в сторону и жмём Alt-F3.
Для настройки следующей точки жмём Alt-F2.
Для сохранения верных координат жмём Alt-F5.
Подводные камни
Опыт показывает, что не стоит торопиться кликать по органам управления и двигать указатель. Часто игры притормаживают, при наведении мыши на кнопку срабатывает отрисовка подсветки и прочие неведанные процессы и торопливость приводит к несрабатыванию клика или захвата при перетягивании и т.п. и как следствие неработоспособность бота. При ручном управлении, люди обычно таких досадных мелочей даже не замечают, так как работает обратная связь через органы зрения. Решение — делать паузы после всех элементарных действий.
Окно игры может произвольно свернуться в следствии появления сообщения от виндозы или ещё по каким причинам. В программе последовательности кликов и пауз стоит предусмотреть клик по иконке свёрнутой игры.
Пишем бота для онлайн-игры на JavaScript с применением AOP
1. Готовим ингредиенты
Важно! Игра должна работать в браузере, а не в клиенте. Причем не на Flash, а на HTML+JavaScript.
На выходе у нас должно получиться расширение для Chrome, которое будет играть вместо нас.
2. Делаем расширение
О том как делается расширение я не буду подробно расписывать. На хабре об этом уже писали, например, тут.
Приведу лишь коды, нужных нам файлов.
В manifest.json
В строчке «matches»: [ «pernatsk.ru*» ] вам нужно будет указать адрес вашей игры.
Файл background.js я использую для случаев, когда хочу инджектить на сайте свой JS кода. Собственно код background.js:
Важно! Если вы не понимаете, что мы делаем в этой единственной функции, то делать бота вам пока рано. Почитайте основы JavaScript.
Вся работа у нас будет вестись в файле injected.js Его код пока такой:
Все эти файлы сохраняем в одной папке bot.
3. Первый пуск бота
4. Добавляем AOP
Для работы бота нам потребуются библиотеки. Мой любимый jQuery уже используется на Пернатске, поэтому добавлять его не будет.
Добавим плагин AOP for Jquery. По хорошему это стоило запаковать в само расширение в виде отдельного файла, но я ленив. Поэтому просто добавим код bin/aop.pack.js первой строкой в наш injected.js.
Проверим, что это работает изменив ai_on
Проверяем, что AOP нормально подключилось. В консоле разработчика теперь будет строчка «jQuery detected!» Сообщение будет только один раз, так как я отключаю совет после первого же срабатывания.
Важно! Прочитайте документацию AOP for Jquery, чтобы понять jQuery.aop.after и bot[0].unweave().
5. Зачем мы будем использовать AOP
6. Учим бота первой команде
В injected.js добавим такой код:
По этой команде наша бот-птичка будет лететь в Пернатске за шишками. Код слегка мудренный, так как в Пернатске есть небольшая защита от ботов.
Когда вы будете писать свои команды я рекомендую сначала опробовать их работоспособность в console, а уже потом переносить код в редактор.
Чтобы протестировать и проверить работу нашей команды запустим в косноле код commands.conessearch() Все работает.
7. Ищем событие на которое должен реагировать бот
Тут есть два метода первый — анализируем код игры. Долго 🙁
Второй метод — воспользоваться AOP, и после всех функций, который срабатывали вывести в лог их имя. Потом выбрать нужные.
Меняем ai_on()
Теперь у нас отражаются только те функции, которые еще не отображались. Их полный список мы храним в fnList.
После пары минут там будут такие варианты функции для прицепки [«clearInterval», «$», «setTimeout», «timerTick», «serverTimeUpdate», «getComputedStyle», «setInterval», «tutorialArr», «showQ», «showQc», «updateBirdData», «viz», «unviz», «weatherUpdate»]
Меняя target и регулярное выражение в method мы можем подобрать ту функцию, которая нам подойдет, чтобы к ней прицепиться. Для примера, я выбираю функцию weatherUpdate теперь каждый раз как будет меняться погода наша птичка будет лететь за шишками.
7. Учим бота реагировать на события
Мы снова меняем код функции ai_on()
Функцияю ai_off нужна, чтобы через консоль выключить бота.
Создание ботов для игр: необходимые программы и инструменты
Игры бывают разные. Но рано или поздно любой геймер задает себе вопрос: «Как сделать бота для игры?». Почему так происходит? Потому что во многих играх:
есть масса рутинных действий, которые ну ж но выполнять человеку;
нужный скилл дается только за деньги или за большое количество игрового времени, деньги тратить не хочется и время — тоже;
хочется «качать» сразу несколько игр подряд, а возможность играть есть только в одну игру;
Бот для игр — это некая компьютерная программа или скрипт, который отвечает за соблюдение последовательности действий игрока, имитирующих действия настоящего живого игрока. То есть главная цель бота — это имитировать действия реального пользователя.
Как сделать бота для игры
Создание ботов для игр намного сложнее создания чат-ботов, поэтому в большинстве случаев понадоб ятся знания одного из языков программирования. Но в т о ж е время создание ботов для игр зависит от того, для какой игры создается бот:
для игры в со цс ети;
для мобильной игры;
для устанавливаемой деск т опной игры.
Уже от этого будет зависеть выбор необходимых инструментов. Плюс есть разные виды ботов для игр. Для чего они нужны:
есть боты, созданные разработчиками самих игр;
есть боты-кликеры, которые выполняют в игре самые простые действия;
есть боты-повторители, которые выполняют одни и те же действия по заготовленному шаблону;
есть боты-имитаторы, которые призваны имитировать действия реальных игроков.
Создание ботов для более простых игр — процесс полегче. Есть небольшой список сервисов, которые смогут помочь вам создать собственный скрипт, некоторые из них даже не требуют знания программирования.
Итак, как сделать бота для простых игр? Попробуйте для этого использовать программы для создания ботов для игр:
Кибор. Есть визуальный редактор, можно создать бота для простой игры;
Zbot. Это уже более продвинутая программа, которая способна создать бота даже для Counter Strike.
Также можно посмотреть еще POD-bot, YaPb и др.
Две популярные среды разработки для игровых ботов:
SikuliX. Для разработки бота при помощи этой среды нужно подучить языки Python или Ruby, при установке нужно будет выбрать.
Итог
Как сделать бота для игры новичку? Для простой игры для этого есть специализированные сервисы. Для игр п ос ерьезнее нужен будет и бот посерьезнее, поэтому без знания языков программирования здесь не обойтись. И мало будет просто его создать, нужно будет сделать его так, чтобы не привлечь к себе лишнего внимания.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
NOMAD BoT
Итак в этой статье я продемонстрирую как создать простого бота основанного на визуальном поиске объектов на экране. Преимуществом данного метода является «незаметность» для различных систем защиты от ботов. Для написания бота мы естественно будем использовать специализированную среду для разработки ботов NOMAD BoT. Если боты создаются для того чтобы сэкономить ваше время на совершение однообразных рутинных действий, то NOMAD создан для того, чтобы сэкономить ваше время при написании бота. В сравнении с написанием ботов на неспециализированных средах программирования или на не очень специализированных разработка на NOMAD может происходить в десятки, а то и в сотни раз быстрее. (т.к. для начала вам еще придется разработать инструменты обнаружения объектов, которые в NOMAD уже встроены готовые). Скачать дистрибутив NOMAD с уже установленным ботом из этой статьи вы можете по этой ссылке (внимание! настройки программы в дистрибутиве рассчитаны на установку его в папку по умолчанию, если вы устанавливаете его в другое место, то измените пути к базе и конструктору с проигрывателем!)
Управлять многими — то же, что управлять немногими. Дело в организации.
Нашей задачей сейчас является демонстрация того, как делается бот программа, а потому для автоматизации мы выберем что-нибудь простое и в то же время всем доступное, например, Калькулятор. Конечно это не онлайн игра, но поверьте, создание бота для онлайн игры ничем не отличается. (внимание пример работает в Windows 8 и Windows 7, причем калькулятор должен выглядеть как на скриншоте, который есть ниже по тексту, т.е. например, в Windows XP калькулятор называется и выглядит иначе, и потому там бот работать не будет)
Для того чтобы начать играть «автоматически» в что нибудь нам необходимо пройти следующие этапы:
Задачей нашего бота будет бесконечно складывать на калькуляторе 2 числа 59 и 3.
Для достижения нашей цели нам необходимо, чтобы наша программа нажимала на кнопки 5 и 9 калькулятора, а в случае успеха на кнопку + и кнопку 3 и затем кнопку =
Следовательно эти объекты мы и должны будем искать на изображении, а затем тыкать в них мышью. Также мы будем анализировать число 59 и число 0 в поле результата, а также кнопку CE, для того чтобы сбросить вычисления на 0 перед началом очередной итерации.
Итак, наш алгоритм: В бесконечном цикле сначала ищем и жмем мышью на кнопку 5, и на кнопку 9. В случае успеха делаем паузу 3 секунды (чтобы успеть насладиться результатом). Затем проверяем есть ли у нас изображение числа 59, если есть то находим и кликаем мышью на кнопки + и 3 калькулятора, если эти операции также выполнены успешно, то находим и кликаем по кнопке = калькулятора. После чего спим 5 секунд. Затем проверяем, если в поле результата нет картинки 0, значит необходимо нажать кнопку CE, чтобы сбросить результаты предыдущих вычислений. После чего итерация повторяется. При нажатии кнопки Esc программа останавливается.
Продемонстрируем код программы которая у нас получилась:
Тут мы забежали немного вперед, написав сразу код, т.к. в NOMAD сначала необходимо создать шаблоны изображений которые мы будем искать. Так если посмотреть в код, то можно увидеть следующие записи: five,nine,fiftynine,plus,three,equal,zero,CE — что это? а это собственно и есть те шаблоны, в NOMAD с ними можно работать из кода как с объектами, т.е. пишем имя объекта в коде и вызываем его метод, например: FindPicture — найти изображение шаблона, MouseClick(‘l’) — найти изображение шаблона и кликнуть левой кнопкой мыши по нему. Для того чтобы подробно изучить возможности и функции NOMAD рекомендую обратиться к документации. А сейчас я в кратце опишу как нам создать недостающие шаблоны:
Во первых создадим базу данных, для этого в Launcher нажмем кнопку ADD, в открывшимся окне заполним в первом поле имя базы данных (например Калькулятор), и во втором поле укажем каталог где мы хотим хранить все что мы напрограммировали. Т.е. собственно исходник нашей программы, или иными словами базу данных. Далее жмем кнопку Save и в списке у нас должна появится запись. Выбираем ее и жмем кнопку Constructor.
Во вторых нужно создать и настроить это конвеер скриншотов, объект который отвечает за фотографирование окна в нашем случае окна калькулятора. Итак, открываем программу в режиме Constructor, в открывшемся окне справа мы должны увидеть такую картину:
На пункте выделенном на картинке голубым цветом жмем правой кнопкой мыши и выбираем пункт меню «добавить конвеер скриншотов». В появившемся окошке указываем его имя — «Calc». И нажимаем кнопку Input. После чего объект с таким именем должен появиться в дереве объектов в разделе ScreenShotPipe. Найдем его там и кликнем на нем левой кнопкой мыши. В левой части программы появится окошко следующего вида (свойства могут идти в другом порядке):
Я уже заполнил его так как оно должно выглядеть у вас. Фактически все уже указанно необходимо только в поле WindName написать слово Калькулятор. Все конвеер готов и мы можем приступать к созданию шаблонов, где я и расскажу зачем вообще мы делали этот конвеер.
В третьих запустим калькулятор и сделаем его снимок, для того чтобы сделать снимок необходимо нажать кнопку ScreenShot в левом верхнем углу Конструктора. После этого у нас появится окно TV со снимком экрана. Теперь нам необходимо нажать кнопку Cut и выделить в окне TV наш калькулятор, результатом этих действий должно быть окно TV с изображением калькулятора.
Нажимаем кнопку Borders ( примечание. с момента написания этой статьи в программе появился режим FixBorders (кнопка черный мониторчик с луной), рекомендую использовать именно его. Используется он точно также как Borders, но работает на динамических изображениях гораздо стабильнее ) и начинаем делать шаблоны. Объясню как это делается на примере шаблона для кнопки «+» — мы должны выбрать на изображении самый характерный его участок, который не повторяется в других местах. Собственно и выбираем сам символ +, нажимаем на кнопку Select, и выделяем этот знак в квадратик:
Кликаем правой кнопкой мыши внутри пунктирного квадратика и у нас появляется окно:
в поле имя которого мы пишем «plus» (так как этот объект у нас в коде был написан) и жмем Input. В разделе Templates дерева объектов у нас появился объект с таким именем. Нажмем на него и слева появится уже знакомое нам окошко:
Тут нам нужно поменять свойство ConnectedScreen в нем мы должны выбрать конвеер скриншотов который мы создавали вначале, т.к. по умолчанию тут выбран глобальный конвеер, который фотографирует весь рабочий стол целиком, а не только наш калькулятор. На этом минимальная настройка шаблона закончена и думаю нам этого будет достаточно. Более подробно об этом можно узнать в документации. Вам лишь осталось поступить аналогичным образом со всеми остальными объектами, которые мы должны добавить в шаблоны. После добавления всех шаблонов дерево объектов должно выглядеть следующим образом:
Очень важно, чтобы наименования в точности включая регистр ввода соответствовали тому, что вы видите на картинке. В примере шаблоны five и nine сделаны другим способом, в режиме ColMap, за подробностями того как это делается предлагаю обратиться к документации. На работу кода программы это не окажет особого влияния и вы можете сделать все шаблоны тем же образом как и шаблон кнопки +. А можете ничего не делать, и скачать готовый дистрибутив с примером
Для того чтобы создать шаблоны fiftynine и zero необходимо делать шаблон участка калькулятора выделенного на картинке:
3) Еще нам необходимо создать графический интерфейс программы через который она будет общаться с пользователем. Для этого необходимо в Конструкторе программы войти в меню «Окна» и выбрать пункт «Дизайнер Формы»
Откроется окно с формой, на которой нужно дважды щелкнуть и из открывшегося окна добавить объект Button в обоих полях формы пишем Start. Жмем ОК и выходим из формы, а на главной форме у нас появилась кнопка Start, нажимаем на нее и появляется опять меню свойств, жмем на закладку Events и видим следующее:
В колонке Value на против события OnClick дважды щелкаем мышью, и в Value автоматически заполняется значение на картинке выше. А в центральном окне появляется текстовый редактор:
Вот этот текст мы и должны заменить кодом, который я привел в начале статьи. Все теперь программа готова. Для запуска необходимо сохранить программу нажав кнопку с изображением двух дискет, затем откомпилировать программу нажав кнопку с картинкой перекрещенных отвертки и ключа, а затем нажать кнопку Launch, или запустить ее из лаунчера. Из конструктора программа всегда запускается в отладочном режиме, поэтому будут показываться отладочные сообщения. Если мы все сделали верно то должны увидеть окно с кнопкой которое мы создали:
Запускаем калькулятор, делаем его видимым на рабочем столе и жмем кнопку старт. Когда надоест жмем кнопку Esc, и ждем сообщения о том что программа закончена.
Вот и все. Сложно? Делать это на обычном языке программирования сложнее в разы. Лично у меня написание этого бота заняло не более получаса, чего не могу сказать об этой статье.
Другие примеры ботов можно поискать на форуме http://nomadbot.com/forum/index.php например, тут
Как сделать (создать) бот программу(кликер)?: 19 комментариев
Приветствую, отличная статья!
Все получилось, но есть несколько вопросов.
Как заставить мышку двигаться на много быстрее, а то
все очень медленно происходит?
Возможно ли с вами связаться лично?
1) Вы скачали обновление? В новых версиях мышка двигается быстро. В Launcher нажать кнопку Update.
2) Зарегистрироваться на форуме и отправить мне личное сообщение.
Как сделать так, чтобы бот кликал только при 100% распозновании
Свойство «к» в итеме шаблона должно быть = 1, тогда будет при 100%. На динамически меняющихся изображениях 100% достигнуть сложно.
Я пытался создать бота для сайта, но заметил странную вещь, на красивых тяжелых сайтах с движущимися элементами на скриншотах в режиме borders границы становятся толще, а если сначала сохранить этот же скриншот сайта в паинте, а потом заскринить в программе, то в borders все по другому, или если закрыть вкладку с сайтом и потом заскринить то тоже все нормально.
Еще хотелось бы узнать какой код нужно написать чтобы программа одновремено нажимала несколько кнопок, ну или по очереди нажимала и удерживала, а потом по очереди отпускала. Например вызывала диспетчер задач.
1) В режиме borders результат зависит от общей яркости изображения. Поэтому если она существенно меняется, то меняются и формы границ. Т.е. данный фильтр существенно снижает чувствительность к изменению цветов, но не исключает ее полностью.
2) функции KeyDown, KeyUp шаблона. или WinApi функции.
Может ли программа двигать курсором удерживая при этом лкм?
Написание бота для флэшевой игры
Зачем?
О лазерной коррекции зрения я подумывал давно, и вот, наконец, решился на процедуру. После недолгого изучения рынка (живу в Питере) выяснилось, что цены по городу везде примерно одинаковые, и заниматься медицинским туризмом смысла тоже нет (в Мск ненамного дешевле). Впрочем, оказалось, что на операции можно заметно сэкономить, т.к. одна из клиник предоставляет разветвлённую систему скидок на свои услуги.
Скидки ветеранам и пенсионерам меня, ясное дело, не интересовали. А вот необычной акцией «поиграй во флеш-игру на нашем сайте и конвертируй набранные очки в скидку» я решил воспользоваться. Подкатом описание процесса.
Вообще идея сперва изумила своей абсурдностью – вроде как считается, что компьютерные игры вредят зрению, и тогда акция похожа на «вычерпай из подвала 10000 вёдер ледяной воды и получи скидку на лечение ревматизма». Сама игра, надо сказать, тоже поразила своей упоротостью – очевидно, что авторы хотели сделать игру без насилия, поэтому легенда гласит: «с помощью технологии LASIK помогите вернуть кротам зрение». Причём, судя по анимации, лечение близорукости производится путём мгновенного испарения пациента.
Ну да ладно, это лирика. На самом деле я сразу попробовал выбить скидку, однако, весь мой геймерский опыт не помог мне с первого раза получить даже 17%. Сыграв несколько раз, я всё же набрал требуемые 17000 очков, но было ясно, что даже 20000 являются недостижимой планкой, не говоря уже о заветных 25000. Проклятые кроты лезут со всех щелей, но быстро прячутся обратно. При этом за «исцеление» крота даётся 100-200 очков, так что пропускать их нельзя. Не знаю, под силу ли это человеку.
Решение пришло в голову сразу же – нужно писать бота, который пройдёт игру за меня! Процесс написания бота на C# подкатом.
Концепция
Глаза
Для начала возьмём OpenCV, чтобы захватывать кадры с экрана и распознавать объекты… СТОП. Мне же не нужно какое-то суперприложение, мне просто нужно получить эту скидку. Стоит ли возиться с OpenCV? Может, проще запустить поток, который в бесконечном цикле будет делать скриншот экрана и просматривать его? Например, так:
А как «лечить» кротов? Очевидно, нужно при запуске найти окно браузера и слать ему сообщение WM_CLICK с нужными параметрами. Впрочем, можно сделать всё проще – физически передвигать курсор на нужное место экрана и эмулировать нажатие клавиш.
Импортируем соответствующие функции WinAPI
И напишем функцию для клика
Теперь, когда все служебные функции есть, осталось написать логику.
Мозги
В общем, поскольку цели у нас появляются в одних и тех же местах, то первое, что приходит в голову – сделать эталонный скриншот экрана, а потом просто проверять, не изменился ли цвет заданных пикселей.
Как хранить координаты целей? Вообще это не так просто. Нужно учитывать разрешение экрана, уровень прокрутки страницы и так далее. Т.е. мало того, что окно игры может иметь разный размер, так оно ещё и может находиться в разных местах экрана. К счастью, я не писал универсальную проходилку игры, мне просто нужно было набрать 25000 очков. Поэтому я решил открывать игру в развёрнутом на весь экран браузере, делать скролл в самый верх страницы и записывать координаты целей как физические координаты пикселей на экране.
А как записывать координаты? Наиболее удобный для пользователя способ – сделать хоткей, по нажатию которого координаты курсора сохраняются, например, в файл. Тогда при появлении крота нужно навести на него курсор и нажать хоткей. Скажу честно, что сперва я так и сделал. Впоследствии оказалось, что куда как проще наделать скриншотов с кротами, измерить положение каждого крота в графическом редакторе, и эти координаты попросту захардкодить. Получилось что-то вроде этого
Добавим на форму кнопку Aim, которая будет делать эталонный скриншот
Теперь добавляем в главный цикл код нашего бота и запускаем!
Что получилось?
Первый результат
Ну, не то, чтобы оно совсем не работало… Во-первых, второпях я как всегда забыл о том, что когда какая-то программа перехватывает пользовательский ввод (особенно таким варварским способом), то её становится проблематично закрыть. После запуска бота мышку невозможно вывести за пределы игрового поля — она будет вечно прыгать по указанным точкам, даже при запуске диспетчера задач. Признаюсь, что я из этой ситуации вышел с помощью перезагрузки… Вообще, если честно, я думаю что именно так роботы и захватят когда-нибудь мир.
Главный рубильник
Наверное, стоит сделать какой-то мудрый алгоритм, который будет определять, что игра закончилась, а также будет отпускать мышь, когда, например, окно с игрой сворачивается. Но, по счастью, мне нужно просто найти способ останавливать бота по моему желанию, и в этом мне поможет знание горячих клавиш Windows. Я просто добавляю обработчик изменения размеров формы, в котором буду останавливать поток с кодом стрельбы.
Теперь, чтобы остановить бота нужно просто нажать Win+D.
Первые проблемы
Но это даже не самое главное. Беда в том, что, хотя наш бот успешно выцеливает кротов, происходит что-то неладное: при попадании по кроту с него выбиваются очки, однако сам крот не исчезает, или же после него остается белый силуэт. Понятно, что в таком случае наш бот продолжает лупить в эту точку до бесконечности (цвет-то поменялся).
Скажу честно, что над этой проблемой я бился довольно долго. В итоге я пришёл к выводу, что в игре как-то криво реализована отрисовка и учёт кротов. Т.е. если я попадаю по кроту раньше, чем он полностью появился из норы, то очки за него мне начисляются, но при этом он продолжает вылезать. А когда крот помечен как «исцелённый», то повторно получить очки за него не получается. Видно, за состояние крота отвечают несколько переменных, у которых нарушена консистентность. Важно, что эта проблема возникала только с кротами, которые вылезают из четырёх нор – с прыгающими по полю и вылетающими в космос никаких сложностей не было.
Я рассудил так — раз в ручном режиме такой проблемы не возникает, то нужно просто делать паузу, а может и вообще эмулировать движение мыши до цели.
После запуска модифицированной программы, которая подводит к кроту указатель за 250 миллисекунд проблема с неисчезающими кротами ушла. Но тут же выявилась другая – подпрыгивающие кроты в нижней части экрана двигаются слишком быстро, чтобы их можно было успеть перевести на него прицел за 250мс. Ведь это из лунок кроты появляются в фиксированных точках, и сидят там некоторое время, а прыгающие кроты проскакивают наши «прицельные точки» очень быстро.
Ну и наконец, при детальном рассмотрении оказалось, что выпрыгивающие в атмосферу кроты на самом деле имеют разные X-координаты, поэтому простое перечисление их позиций было бы слишком утомительным. Похоже, надо менять концепцию…
Новая концепция
Итак, кроты появляются в разных местах, поэтому отслеживать их по координатам невозможно. Неужели придётся делать распознавание образов? Не хотелось бы. Попробую перед этим ещё одну «тупую» реализацию. Что общего у всех кротов? Скафандры и ботинки видны не у всех. Но у всех кротов видна голова в шлеме. К тому же шлем имеет весьма необычный цвет… Что если сканировать всё изображение на предмет наличия этого голубоватого оттенка? Попробуем!
На скриншоте я посмотрел координаты рабочей области флешки и цвет шлема. Теперь на своём Core i5 я просто перебираю в цикле все пиксели с помощью супер-тормозного метода GetPixel, и стреляю при совпадении цвета с эталонным. При таком подходе время выполнения одного цикла составляет около 200 миллисекунд, что кажется допустимым значением. Запускаем!
И новые проблемы
Всё оказалось не так просто – на шлеме есть не одна точка эталонного цвета, поэтому бот при появлении крота начинает лупить в белый свет как в копеечку, игнорируя других пациентов. Решение нашлось довольно просто – будем сохранять координаты последнего выстрела, и при обработке текущего кадра игнорировать пиксели в окрестности этих координат.
Вторая проблема данного подхода состоит в том, что кроты двигаются, поэтому нередко за время обработки кадра крот успевает убежать от целебного пучка фотонов. К тому же выбранный нами цвет находится на самом краю шлема, поэтому даже при небольшой задержке мы теряем пациента.
Для начала сократим время обработки кадра. Вообще для этого нужно скопировать изображение в область прямого доступа к памяти, и работать с байтиками напрямую… Но мы просто изменим шаг сканирующих циклов на двойку, тем самым увеличив скорость сканирования картинки в четыре раза. Сильнее увеличивать шаг уже не получится безболезненно – некоторые зоны пикселей будут пропускаться.
Сортировка пациентов
Ещё для увеличения эффективности стрельбы по прыгающим кротам стоит останавливать обработку кадра после поражения первой найденной цели. Поясню – пусть на экране находтся два крота, тогда пока мы стреляем по одному, второй уже успевает немного сместиться, в то время как на старом кадре у нас остались его прежнее изображение. В этот момент мы сталкиваемся с одной из глобальных проблем всех си-подобных языков – невозможность прерывания двух вложенных циклов с помощью команды break. Я в таки случаях совершаю ужасное кармическое преступление, используя оператор goto.
Наконец, не будем забывать о летающих тарелках, роботах и ракете, которые нужно отслеживать строго в определённых местах. В итоге цикл стал выглядеть так.
Каков итог?
В общем, эта программа уже успешно набирала 21-22 тысячи очков. Для получения 25 нужно было менять некоторые магические значения типа задержек и координат выстрелов для «очереди». В определённый момент звёзды сложились удачно, и я перевалил заветную отметку в 25000, для этого потребовалась пара десятков запусков.
На всю работу с момента создания проекта до момента распечатывания купона со скидкой ушло два вечера. Сейчас я понимаю, что работу можно было бы сократить, если бы алгоритм был продуман заранее. Однако я сэкономил кучу времени за счёт того, что постоянно себя одёргивал, когда мне приходили в голову мысли о создании продукта, который бы проходил игру за человека.
Я изначально писал плохой с точки зрения архитектуры и функциональности код, стараясь решить конкретную задачу за минимальное время. Эта программа работает только на моей конфигурации монитора и требует довольно много вычислительных ресурсов, но она решает свою задачу, и этого достаточно. Собственно этот пост и задумывался как иллюстрация эффективности подобного подхода, т.к. в прошлом я нередко упускал многие возможности именно из-за «перфекционизма» и желания написать идеальный код, вместо того, чтобы просто сделать вещь, которая решает задачу.
Мне не совсем непонятно, на что рассчитывали создатели игры, потому что как мне кажется, вручную игру пройти нереально. Возможно, концепция как раз предполагала, что скидки в 25% достойны только красноглазики, которые могут написать бота.
UPD. В комментариях изложены ещё способы получения скидки. К моему стыду, о самом простом из них я даже не подумал… Получается, пост как иллюстрация того, что не нужно делать сложно, когда можно сделать просто, удался именно благодаря комментаторам. Действительно, бота можно было и не писать… Надеюсь, это послужит уроком не только мне, но и остальным несчастным, страдающим компьютерной болезнью, выявленной и классифицированной полсотни лет назад.
А что касается мистера Френкеля, который затеял всю эту деятельность, то он начал страдать от компьютерной болезни — о ней сегодня знает каждый, кто работал с компьютерами. Это очень серьезная болезнь, и работать при ней невозможно. Беда с компьютерами состоит в том, что ты с ними играешь. Они так прекрасны, столько возможностей — если четное число, делаешь это, если нечетное, делаешь то, и очень скоро на одной-единственной машине можно делать все более и более изощренные вещи, если только ты достаточно умен.
Через некоторое время вся система развалилась. Френкель не обращал на нее никакого внимания, он больше никем не руководил. Система действовала очень-очень медленно, а он в это время сидел в комнате, прикидывая, как бы заставить один из табуляторов автоматически печатать арктангенс x. Потом табулятор включался, печатал колонки, потом — бац, бац, бац — вычислял арктангенс автоматически путем интегрирования и составлял всю таблицу за одну операцию.
Абсолютно бесполезное занятие. Ведь у нас уже были таблицы арктангенсов. Но если вы когда-нибудь работали с компьютерами, вы понимаете, что это за болезнь — восхищение от возможности увидеть, как много можно сделать. Френкель подцепил эту болезнь впервые, бедный парень; бедный парень, который изобрел всю эту штуку.