Игровые боты. Начало

    Что может быть интереснее процесса игры в игры? Правильно! Процесс наблюдения за тем, как играет в игры написанный тобой бот.

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

    Введение

    Боты для онлайн игр я бы грубо разделил на 3 разновидности по способам реализации:
    1. Боты не использующие приложение игры. Имитирующие протокол обмена с сервером.
    2. Боты работающие с процессом приложения игры. В случае с Web, работающие с окном браузера.
    3. Боты работающие со скриншотом и имитирующие устройства ввода мышь и клавиатуру.

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

    Вторая разновидность более реальна и может быть реализована. Бот второго вида получает полезную информацию из памяти процесса игры. Недостаток — версии клиентов могут регулярно обновляться и тогда может потребоваться заново искать интересующие адреса памяти.

    Мы рассмотрим третюю разновидность ботов, т.к. ИМХО они более привлекательны, хоть и не лишены недостатков.
    А так же, такой подход более спортивный :-)

    В этой статье я рассмотрю набор инструментов для самого простого бота для Windows.

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

    Код

    Для разработки приложений я буду использовать Qt Creator + Qt 5 либы (так мне привычнее) и раз бот для Виндовс то + windows.h (WinAPI).

    Инклуды:
    #include <windows.h>   // WinAPI
    #include <iostream>    // std::cout
    #include <unistd.h>    // sleep(), usleep()
    #include <math.h>
    


    Хидер бота:

    // Индексы точек
    enum {
        menu=0,
        elm_1,
        points_cnt
    };
    
    class MyBot
    {
    public:
        MyBot();
        void run();
        void move_to(int inx);
        void lclick_to(int inx);
        void rclick_to(int inx);
        void drag(int from_inx,int to_inx);
        POINT point[points_cnt];
    };
    


    Конструктор:
    MyBot::MyBot() :
        // Массив координат органов управления (по которым мы будем кликать мышкой)
        point({
          {100,100}, // 0 - menu
          {130,130}, // 1 - elm_1
        })
    {
    }
    


    Регистрация горячих кнопок для управления ботом:

        RegisterHotKey((HWND)Widget::winId(), 101, MOD_ALT, VK_F1);    // Запуск бота
        RegisterHotKey((HWND)Widget::winId(), 102, MOD_ALT, VK_F2);    // inx++
        RegisterHotKey((HWND)Widget::winId(), 103, MOD_ALT, VK_F3);    // Проверить точку inx
        RegisterHotKey((HWND)Widget::winId(), 104, MOD_ALT, VK_F4);    // Запомнить точку inx
        RegisterHotKey((HWND)Widget::winId(), 105, MOD_ALT, VK_F5);    // Вывести в консоль массив координат
    


    Обработка событий нажатия кнопок управления ботом:

    int inx=0;
    MyBot bot;
    
    bool Widget::nativeEvent(const QByteArray & eventType, void * message, long * result){
        Q_UNUSED(result);
        Q_UNUSED(eventType);
        MSG* msg = reinterpret_cast<MSG*>(message);
        if(msg->message!=WM_HOTKEY)return false;
    
        switch(msg->wParam){
        case 101: // Alt-F1 - запуск бота
            bot.run();
            return true;
        case 102: // Alt-F2 - inx++
            if(inx<points_cnt-1)inx++;
            return true;
        case 103: // Alt-F3 - Проверить точку inx
            bot.move_to(inx);
            return true;
        case 104: // Alt-F4 - Запомнить точку inx
            GetCursorPos(&bot.point[inx]);
            return true;
        case 105: // Alt-F5 - Вывести в консоль массив координат
            for(i=0;i<points_cnt;i++){
                std::cout << "{" << bot.point[i].x << "," << bot.point[i].y << "}, //" << i << std::endl;
            }
            return true;
        }
        return false;
    }
    


    Перемещение указателя мыши к нужной точке:
    (выполнено не очень аккуратно, обещаю исправиться :-))
    #define width 1920
    #define height 1080
    
    void MyBot::move_to(int inx){
        int x=point[id].x;
        int y=point[id].y;
        POINT pt;
        GetCursorPos(&pt);
    
        int from_x=pt.x;
        int from_y=pt.y;
    
        int to_x=x;
        int to_y=y;
    
        int dx=to_x-from_x;
        int dy=to_y-from_y;
    
        float fdx;
        float fdy;
        int loop_cnt;
    
        if(abs(dx)>abs(dy) && dx!=0){
            fdx=dx<0? -1.0 :1.0;
            fdy=(float)dy/abs(dx);
            loop_cnt=abs(dx);
        }
        else if(dy!=0){
            fdy=dy<0? -1.0 :1.0;
            fdx=(float)dx/abs(dy);
            loop_cnt=abs(dy);
        }
        else return;
    
        // двинуть за 1 секунду
        int time=1000000/loop_cnt;
        float fx=from_x;
        float fy=from_y;
        for(int i=0;i<loop_cnt;i++){
            fy+=fdy;
            fx+=fdx;
            int nx=(fx)*(65536 / width);
            int ny=(fy)*(65536 / height);
            mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,nx,ny,0,0);
            usleep(time);
        }
        usleep(50000);
    }
    


    Клики:

    void MyBot::lclick_to(int inx){
        move_to(inx);
        mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
        usleep(50000);
        mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
        usleep(100000);
    }
    
    void MyBot::rclick_to(int inx){
        move_to(inx);
        mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
        usleep(50000);
        mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
        usleep(100000);
    }
    


    Перетаскивание:

    void MyBot::drag(int from_inx, to_inx){
        move_to(from_inx);
        usleep(50000);
        mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
        usleep(70000);
        move_to(to_inx);
        mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
        usleep(30000);
    }
    


    Работа бота:

    void MyBot::run(){
        rclick_to(menu);  // кликнем правой кнопкой для вызова контекстного меню
        lclick_to(elm_1); // кликнем левой кнопкой по строке меню
    }
    


    Мануал юзера

    Перед запуском бота горячей кнопкой Alt-F1, бот следует сначала настроить, определив верные координаты органов управления по которым бот будет кликать.
    Для запоминания координат точки наводим указатель месту и жмём Alt-F4.
    Для проверки корректности точки отводим указатель в сторону и жмём Alt-F3.
    Для настройки следующей точки жмём Alt-F2.
    Для сохранения верных координат жмём Alt-F5.

    Подводные камни

    Опыт показывает, что не стоит торопиться кликать по органам управления и двигать указатель. Часто игры притормаживают, при наведении мыши на кнопку срабатывает отрисовка подсветки и прочие неведанные процессы и торопливость приводит к несрабатыванию клика или захвата при перетягивании и т.п. и как следствие неработоспособность бота. При ручном управлении, люди обычно таких досадных мелочей даже не замечают, так как работает обратная связь через органы зрения. Решение — делать паузы после всех элементарных действий.

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

    Qt Creator: qt-project.org/downloads
    Исходный код проекта на гитхабе: github.com/rumaster/my_bot_v1

    P.S. Не подумайте что я ярый противник онлайн игр, раз публикую исходники ботов. Я противник дискриминации ИИ (ботов) и за развитие онного. А ещё, игры — двигатель прогресса.

    P.P.S. Говоря ИИ, я подразумеваю программу способную получать и обрабатывать (анализировать) информацию, планировать и выполнять действия в соответствии с целями и результатами анализа ситуации.
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 17

      +3
      Первая разновидность скорее гипотетическая, т.к. протоколы, как правило, закрыты и не тривиальны.

      Особенно браузерные (на html, без флэша, джавы и прочих активиксов). В подавляющем большинстве случаев достаточно средств браузера, чтобы исследовать протокол, и даже в нём же написать бота :)
        0
        Согласен, web в данном случае исключение. Я имел в виду игры типа WoT.
        +3
        Автор, поздравляю. Вы изобрели autoit и тысячи других аналогичных программ.
        Первый вид ботов самый практичный, а не гипотетический как вы считаете и позволяет организовывать действительно полезные ботофермы.
          0
          О том, какой вид самый практичный, вопрос спорный. Не сомневаюсь, что бот первого типа самый эффективный, но его реализация не всегда оправдана. Как я выше писал для веб ботов может быть оправдано, но для случаев, когда передаются бинарные данные с неизвестной структурой, практичность первого вида ботов падает.

          Потом, написание ботов не для всех и не всегда является вопросом коммерческой выгоды (я о ботофекрмах).
          Иногда ботов делают для личного пользования и исключительно из интереса к искусству.
          0
          Про других ботов ожидал здесь увидеть… Где бы интересное почитать по поводу программирования игровых противников?
            –2
            Создание бота — процесс интересный.
            Но как только бот будет создан, интерес к игре пропадает абсолютно. Проверенно :(
              +2
              Если бот фармит, а сам только фанишься в певепе, то нормально.
                0
                Ну кому то может и интересно. Я высказал своё мнение и то, что видел на примере нескольких своих знакомых.
              0
              Вот скоро в России ArcheAge выходит, для ботмейкера очень привлекательная цель.
              1. Море автоматизируемой рутины в стиле «Весёлой фермы»
              2. В нём уже есть встроенный скриптовый язык (Lua), позволяющий создавать аддоны. Осталось только пробросить туда дополнительные функции, написав соответствующий патч.
              3. Надо будет как-то догонять владельцев премиум-пака, которые зашли уже сегодня, а не сидеть же для этого в режиме 24/7?
              4. Ну и наконец просто крайне популярная игра. Не сомневаюсь, что будут даже заказы на ботов — голдселлеры не дремлют
                0
                голдселлеры не дремлют

                Моя уже рассылку получил от них, что продажа в ArcheAge пойдет чуть ли не с первого дня, предоплату уже берут
                0
                Для запоминания координат точки наводим указатель месту и жмём Alt-F4.

                А вот это будет не просто…
                  0
                  Почему?
                  К тому же, это лишь простейший каркас для простейшего бота. Построенный по принципу «простота залог здоровья».
                  Возможно координаты будут рассчитываться из каких то соображений, а не тупо вытаскиваться из массива.
                  +2
                  Alt+F4 — это несомненный успех.
                    0
                    Если вы о close window, то его не будет. Этот хоткей идёт в жертву боту :-). Да и кто мешает назначить другие хоткеи?
                    0
                    Для эмуляции нажатий клавиш и дрыганья мышью на X11 (Linux/OSX) могу посоветовать xdotool/libxdo (или XTest + XLib, на которых xdo построен).
                      0
                      Я просто оставлю это здесь.
                        0
                        Да, штука хорошая, пользовались ей на одном проекте, автозаполнение анкеты на сайте.
                        Но есть у нее косяк, она использует распознавание картинок для поиска элементов на экране, так вот
                        примерно 4-5 из 100 поисков элементов на экране, ошибочное.
                        Находится совсем не тот элемент, отсюда много ошибок при выполнении алгоритма.
                        Так и не смогли побороть этот момент.

                      Only users with full accounts can post comments. Log in, please.