Пишем бот для рыбалки в игре Albion Online на языке Python

image

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

И еще меньше игр в жанре MMORPG.

Однако, где-то пол года или год назад я узнал что под линукс портировали игру Albion Online.
Игра очень занимательная, однако занимает достаточно большое количество времени. И дабы не тратить свои драгоценные часы жизни по напрасну, я решил написать бота. Который будет фармить мне ресурсы, пока я буду заниматься своими делами.

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

Итак, суть рыбалки в альбион онлайн проста, берете удочку, подходите к водоему, зажимаете кнопку, дабы закинуть наживку, ждете в течении определённого времени поклевки.

image

Когда клюет, вы должны опять нажать на кнопки и сыграть в мини-игру.

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

Итак, все это дело мы будем автоматизировать. По средствам компьютерного языка python. Начать я решил с самого сложного, а именно с момента, где начинается игра с поплавком. Тут снова мне на выручку пришла моя любимая библиотека с компьютерным зрением OpenCV. Запустив ее мы можем обнаруживать объекты к примеру на картинках. Однако сама библиотека не знает что именно нам нужно обнаружить. Конечно существуют множество шаблонов где представлены различные предметы для их определения. Однако, там точно нет поплавков для Albion Online.

Зато в данной библиотеке есть замечательная функция поиска по заданному шаблону. И в качестве шаблона я просто взял скриншот нашего поплавка.

image

И как мы видим все прекрасно нашлось на картинке.

А разница между картинкой и потоковым видео не велика, ведь по сути это просто поток картинок с очень быстрой скоростью, и несколько строчек кода. И вот мы уже можем находить поплавок на потоковом видео.

Код
import numpy as np
import cv2
from mss.linux import MSS as mss
from PIL import Image
import time
import pyautogui as pg
import cv2
import mss
import numpy

template = cv2.imread("2019-07-02_06-55_1.png", cv2.IMREAD_GRAYSCALE)
w, h = template.shape[::-1]

with mss.mss() as sct:
    monitor = {"top": 40, "left": 0, "width": 800, "height": 640}

    while "Screen capturing":
        last_time = time.time()
        img = numpy.array(sct.grab(monitor))
        cv2.imshow("OpenCV/Numpy normal", img)
        print("fps: {}".format(1 / (time.time() - last_time)))
        gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(res >= 0.7)
        for pt in zip(*loc[::-1]):
            cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 3)
        cv2.imshow("Frame", img)
        key = cv2.waitKey(1)
        if cv2.waitKey(25) & 0xFF == ord("q"):
            cv2.destroyAllWindows()
            break


Идем далее. Сам поплавок двигается туда-сюда и мы также должны его двигать, нажимая кнопку на мышке.

А посему, нам нужны его координаты. И для этого нас выручают вот эти строчки.

for p in img:
                pts = (pt[0],pt[1])
                x = (pt[0])
                y = (pt[1])
                print (x)
                cv2.circle(template,pts,5,(200,0,0),2)
                cv2.putText(img, "%d-%d" % (x,y), (x+10,y-10),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, color_yellow, 2)

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

if 100 < x < 500:
                        pyautogui.mouseDown(button='left')
                        time.sleep(1)
                        pyautogui.mouseUp(button='left')
                        x = 0

И сама мини игра успешно выигрывается.

image

Засунем все это дело в функцию и пока оставим.

Затем вернемся к изначальной части, где мы должны следить за поплавком.

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

В таком случае мы возьмём тот несколько иной метод. Суть его в том, что мы анализируем, скажем так разницу в пикселях внутри отслеживаемого фрагмента. Которая, если поплавка нет приближается к нулю.

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

Код
def screen_record():
    sct = mss.mss()
    last_time = time.time()

    while(True):
        img = sct.grab(mon)
        print('loop took {} seconds'.format(time.time() - last_time))
        last_time = time.time()

        img = np.array(img)
        processed_image = process_image(img)
        mean = np.mean(processed_image)
        print('mean = ', mean)

        if  mean <= float(0.11):
            print('SSSSSSSS ')
            pyautogui.click(button='left')
            break
            return
        else:
            time.sleep(0.01)
            continue
        return
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break


И мы их производим, а именно нажимаем на кнопку мыши. Также засовываем это в функцию.

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

while "Черный":
    time.sleep(1)
    pyautogui.moveTo(431,175,duration=1)
    pyautogui.mouseDown(button='left')
    pyautogui.moveTo(450.200,duration=1)
    pyautogui.mouseUp(button='left')
    time.sleep(2)
    screen_record()
    time.sleep(0.01)
    ss()

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


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

Весь скрипт:

Код
import numpy as np
import cv2
from mss.linux import MSS as mss
from PIL import Image
import time
import pyautogui as pg
import imutils
import mss
import numpy
import pyautogui

template = cv2.imread("2019-07-02_06-55_1.png", cv2.IMREAD_GRAYSCALE)
w, h = template.shape[::-1]

color_yellow = (0,255,255)

mon = {'top': 80, 'left': 350, 'width': 100, 'height': 100}

def process_image(original_image):

    processed_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)

    processed_image = cv2.Canny(processed_image, threshold1=200, threshold2=300)
    return processed_image

def ss():
    op = 1
    with mss.mss() as sct:

        monitor = {"top": 40, "left": 0, "width": 800, "height": 640}

        while "Screen capturing":
            last_time = time.time()

            img = numpy.array(sct.grab(monitor))


            gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED)
            loc = np.where(res >= 0.7)
            op += 1
            print (op)
            for pt in zip(*loc[::-1]):
                cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 3)
                for p in img:
                    pts = (pt[0],pt[1])
                    x = (pt[0])
                    y = (pt[1])
                    print (x)
                    if 100 < x < 490:
                            pyautogui.mouseDown(button='left')
                            time.sleep(2)
                            pyautogui.mouseUp(button='left')
                            x = 0
                            break
                    else:
                            continue
                    break
                else:
                        continue
                break
            key = cv2.waitKey(1)
            if cv2.waitKey(25) & 0xFF == ord("q"):
                cv2.destroyAllWindows()
            if op > 35:
                return

def screen_record():
    sct = mss.mss()
    last_time = time.time()

    while(True):
        img = sct.grab(mon)
        print('loop took {} seconds'.format(time.time() - last_time))
        last_time = time.time()

        img = np.array(img)
        processed_image = process_image(img)
        mean = np.mean(processed_image)
        print('mean = ', mean)

        if  mean <= float(0.11):
            print('SSSSSSSS ')
            pyautogui.click(button='left')
            break
            return
        else:
            time.sleep(0.01)
            continue
        return
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

while "Черный":
    time.sleep(1)
    pyautogui.moveTo(431,175,duration=1)
    pyautogui.mouseDown(button='left')
    pyautogui.moveTo(450.200,duration=1)
    pyautogui.mouseUp(button='left')
    time.sleep(2)
    screen_record()
    time.sleep(0.01)
    ss()


Те кто любит сказать, что это бесполезная трата времени, я замечу, что это лишь инструмент, эти библиотеки вы можете применить и в других проектах. Само компьютерное зрение применяется как при наведении баллистических ракет, так и в программах для помощи инвалидам. Куда вы решите их применить, только ваше желание.

Всем спасибо за внимание.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 35

    +1
    По какому алгоритму работает matchTemplate? Насколько чувствительна к эффектам типа день/ночь (если они присутствуют)?
    Ещё многие клиенты игр (ММО как минимум) мониторят манипуляции с вводом, ну или по-крайней мере пытаются. Главное, бан не поймайте.
      0
      Там попиксельно вычисляется «расстояние», встроено несколько методов — квадрат разности, пара корреляций, плюс их нормированные версии. Если при день/ночь искомая картинка меняется, то и не факт что найдет. Но можно работать с контурами, например.
        0
        Да никто не пытается кроме безумных азиатов.

        При любой эмуляции ввода в винде API всегда выставляет определённый бит в сообщении о том, что это сообщение эмулировано, а не — от реального устройства. Проверить этот бит — раз плюнуть. Это самая элементарная защита от читера-нуба, которую можно реализовать без особых затрат, но никто не заморачивается.
        Адекватно эмулировать можно только драйвером, но тогда легко спалить даже юзермод античитом неподписанный загруженный драйвер в test-режиме.

        Короче, было бы желание и важность борьбы с читами.
        Вполне учитывают менеджеры, что будут использовать читы. И в экономику это очень даже закладывается изначально. Баны начинаются только после того, как игрок отыграл на средний чек.
        Это про гриндилки. В competition играх чуть иначе всё устроено.
        0
        > воспользуемся библиотекой PyAutoGUI
        О, как то искал под Linux замену AutoIT. Похоже эта штука должна подойти.
          0
          Есть еще альтернатива для Java — sikuli.
          Тоже когда то писал бота для bluestacks, вполне себе годно.
          0
          много играю в idle игры. И если у игры неспешный геймплей, то тоже пишу бота, только использую для этого программу автоматизации AutomaticMouseAndKeyboard. Считаю ее одной из самых удобных в этом плане, хотя бы из за встроенной возможности искать точно заданную картинку на экране. Недавно прикрутил к ней Capture2Text и могу определять написанный текст внутри игры, в частности для определения требуемых цифр. Вот теперь может еще и openCV задействую
            0
            Что можете посоветовать из подобного жанра?
              0
              последние которые меня наиболее сильно зацепили: kittens game (есть в браузере и на мобилке), zomidle (браузер, steam, мобилка), realm grinder (браузер, steam, мобилка)
              0

              Если для idle игры нужен бот — то это уже не idle игра, а кликер. Или вовсе RTS :-)

                0
                кликер это поджанр idle игр. А rts вообще из другой оперы )
              +4
              Это все конечно замечательно. Но есть одно «но».
              13.3 No Manipulation
              use software playing in place of the player (such as scripts or bots)
              Прошу иметь это в виду всем, кто решит повторить.
                +1
                Увы, реалии таковы, что надо встроить в бот защиту от антибота, в особенности от антибота-нейросети. В частности рандомные задержки операций, имитирующие человеческую реакцию и рандомные фейлы, чтоб сие стало более похоже на игрока… так же нужны рандомыне перерывы между забросами.
                  0

                  На Go есть удобная библиотека для автоматизации robotgo. Среди прочего там есть и функция MoveMouseSmooth, имитирующая движение мыши человеком.

                    +3
                    Писали как-то бота (коллективом из 3х разработчиков ) для одной популярной браузерки, добавили задержку ввода, рандомные действия, всё почти как у людей. Начали играть — всё равно всех забанили, говорят не может человек заниматься такой скукотищей по 16 часов в сутки каждый день.
                      0
                      Увы, реалии таковы, что надо встроить в бот защиту от антибота, в особенности от антибота-нейросети. В частности рандомные задержки операций, имитирующие человеческую реакцию и рандомные фейлы, чтоб сие стало более похоже на игрока…

                      Человеческую реакцию хорошо бы имитировать ещё и случайными матами в микрофон при неудаче. И мышка чтоб ещё отключалась и возвращалась через N минут, будто её об стену разбили и подключали новую.
                      +1
                      2 вопроса:
                      1) Разве бот не нарушает правила игры?
                      Я не против автоматизации, это интересная тема. Но, если формально это нарушение правил, стоит это упомянуть.
                      2) Почему бы, перед публикацией текста, не засунуть его хотя бы в Ворд? Да, это не мой государственный язык, но даже я насчитал 7 орфографических и более 30 пунктуационных ошибок.
                      Кровавые слезы заливают телефон, пока пишется этот комментарий.
                        0
                        Выделяете ошибку, нажимаете Ctrl+Enter, добавляете комент и автору прилетит письмо об ошибке :)

                        Но текст перед отправкой нужно проверять, согласен.
                          +1

                          Увы, у меня на телефоне нет ни ctrl, ни enter.

                          0
                          Я пару раз читал правила разных игр. Пришёл к выводу, что играя без бота ты всё равно нарушаешь. Тогда какая разница играть с ботом или нет?
                          Особенно впечатлил варгейминг. Меня забанили на форуме, я спрашиваю за что-отвечают. Я говорю, что этого не делал(я использовал очень аккуратные формулировки), долго думают, но отвечают. Я с удивлением смотрю на правила и понимаю что их поменяли уже после того, как меня забанили.
                          P.S. Я сейчас пишу более интересную(с точки зрения закона) вещь. По сути продвинутый UI. Но выводится он в прозрачной форме ПОВЕРХ игры. Т.е. интерфейс в игре я вижу, но формально это другое приложение.
                          –8
                          Те кто любит сказать, что это бесполезная трата времени, я замечу, что это лишь инструмент, эти библиотеки вы можете применить и в других проектах. Само компьютерное зрение применяется как при наведении баллистических ракет, так и в программах для помощи инвалидам. Куда вы решите их применить, только ваше желание.

                          То есть, можно было написать программу для помощи инвалидам, но вы решили написать чит для игры?
                          Oh, wait…
                            +5
                            То есть, можно было написать программу для помощи инвалидам, но вы решили написать этот комментарий?
                              +4
                              Если хочешь освоить новую технологию — ее надо применять там, где тебе лично это интересно(если это возможно!), тогда обучение проходит легче. А если писать абстрактную фигню — то есть немало шансов плюнуть на эту затею, не доведя ее до конца…
                              0
                              И дабы не тратить свои драгоценные часы жизни по напрасну...

                              Но ведь в этом и задумка всех (онлайн ММОРПГ) игр. Дайте угадаю, рыбалка там ведь не основное занятие, а вспомогательное, занимающее время?..
                                0
                                А за это разве не банят? Если взять тот же WoW то теперь там с этим всё строго.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    Вот вот, купил монитор побольше, чтобы лучше видеть противников-забанили.
                                    Настроил чувствительность мышки-бан.
                                    P.S. Вспоминается CS 1.6. Когда для стрельбы из снайперской винтовки БЕЗ режима увеличения в центр монитора приклеивали бумажку.
                                      0
                                      Это какой-то CS 1.0.
                                      В 1.6 уже вроде бы был нехилый разброс при стрельбе без оптики.
                                        0
                                        Насколько я помню, разброс там был при стрельбе в движении. Стрельба при остановке без оптики была нормальной. А может действительно версия была ниже.
                                    0
                                    Да ладно вам.
                                    В вове обычная картина, когда бегает паровоз из нескольких человек по одному и тому же маршруту на каче, одновременно поворачивают, одновременно начинают атаковать, одновременно срываются в другую локацию. Смотришь на это и смешно.
                                    Вов сейчас только на ботоводах и держится. И всем насрать.

                                    К тому же, у них очень лайтовый и лояльный античит. Это вам не китайский адок с драйверами, виртуализацией, грязными хуками и прочими БСОДами в качестве античита.
                                      0
                                      В играх с платным созданием аккаунта ботов не банят моментально, их банят раз в N дней, чтобы ботоводы успевали отбить фармом стоимость аккаунта и у них был резон купить еще пачку новых аккаунтов.
                                        +1
                                        Соглашусь что ботоводство в определенной степени выгодно, но банят раз в N дней скорее по другой причине, а именно из-за того, что ботоводам сложнее подстраиваться под античит.
                                          0
                                          Адекватные разработчики ботов и так видят, что обновился античит, реверсят его и смотрят, что поменялось. При этом, в идеальном случае нужно пользователю показывать предупреждение, что-то типа: «Мы ещё не обработали обновления в античите, используйте бота на свой страх и риск или дождитесь его обновления».
                                    0
                                    отличная статья. большое спасибо за инфу, давно думал написать бота для одной мобильной игрушки но не доходили никак руки. теперь есть с чего начать, где копать :)
                                      0
                                      Идея интересная, но это пока бот не встретит первого ганкера ;)
                                        0
                                        Бота ганкера или просто игрока-ганкера? :)
                                        А то вроде особо ботов ганкеров не встречал, это же надо уже намного больше действий выполнять (учитывать параметры противника и много других вещей), особенно если вы хотите «ботом-ганкером» убить обычного игрока.

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое