Python, под пиратским флагом

image Йо-хо-хо, хабровчане!

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

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


Сразу стоит сделать некоторые ремарки:

  • Если вы святоша и веско, резко, решительно против любого мухлежа в играх — можете смело закрывать статью.
  • Если вы «труъ» программист и готовы брызжа слюной доказывать, что питон фигня и новичков сразу нужно макать в ручное управление памятью, яки младенца в святую воду — можете смело закрывать статью.
  • Если же вы мега квалифицированный программист без предрассудков — выбор за вами, но скорее всего мой быдлокод будет резать вам глаз и подобные штуки вы сами делаете на раз плюнуть.
  • Новички и любители интересных задачек — добро пожаловать на борт.

Соль задачи


Есть игра GuildWars2, в ней запущен рождественский эвент (мини игра), которая очень похожа на guitar hero только с колокольчиком.

image

Смысл игры заключается в своевременном нажатии кнопок-нот 1-2-3-4 и 6-7-8-9 в зависимости от того, какой кружок по какой дорожке приедет к центру, где стоит персонаж. Если очень интересно, то можно посмотреть видео на ютубе, набрав guild wars 2 choir bell.

За полное прохождение, пусть и с погрешностями, дают максимальное количество ценных подарочков, которые можно продать на рынок по цене примерно 5.5 серебра за штуку. Я подсчитал, что за сутки неприрывного прохождения этого эвента, можно делать ~3300 подарочков а это больше 180 чистого золота, цена которому 2 рубля за ед. на черном рынке. Копейки в абсолютных величинах но очень неплохо в сравнении с тем же криптомайнингом, а? Особенно если учесть, что для этого нам не требуется дорогостоящая видеокарта или платный аккаунт.

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

Шаг 0. Анализируем


Для автоматизации нам нужно всего 2 вещи: распознавать пиксели и нажимать кнопки.
Тут требуется сделать небольшое отступление и сказать, что я совсем не будучи программистом, пробовал быдлокодить на с++, с#, PHP, delphi и даже ассемблере в среде masm32. Выбор питона на этой стадии был почти случайным. Я просто подумал «А почему бы не попробовать до кучи на питоне? Вдруг будет удобнее?». Это не был какой то осознанный выбор, я тогда еще и не предполагал, насколько питон классный.

Нужно было понять, как можно зацепиться за цвета пикселей и я начал искать простую пипетку, которая показывала бы цвет под указателем мышки и его rgb значение. Из игры я записал на бандикам видео для анализа, поэтому фотошоп и редакторы изображений не подходили. Не нарезать же в самом деле видео на скриншоты. Мне нужно было что то простое, работающее в режиме реального времени и показывающее координаты. К сожалению гугл не нашел мне подходящей утили и я решил состряпать ее сам. Вот что получилось:

Код пипетки спрятал под спойлер
from graphics import *# Здесь и далее импортируемый модуль графических примитивов(скачивается отдельно)
import pyautogui #Здесь и далее импортируемый модуль автоматизации ( скачивается отдельно )
import time # время же. (Стандартный модуль)

def main():# определяем мэйн функцию
    win = GraphWin("pipetka", 200, 200, autoflush=True)#создаем графическую форму размером 200х200 и элементы на ней
    x, y = pyautogui.position()#получаем в x, y координаты мыши
    r, g, b = pyautogui.pixel(x, y)# получаем в r, g, b цвет

    ColorDot = Circle(Point(100, 100), 25)# создаем точку, отображающую цвет
    ColorDot.setFill(color_rgb(r, g, b))# устанавливает ей заливку из ранее полученных цветов
    ColorDot.draw(win)# рисуем на форме win

    RGBtext = Entry(Point(win.getWidth()/2, 25), 10)# создаем RGB вывод
    RGBtext.draw(win)# рисуем на форме win

    RGBstring = Entry(Point(win.getWidth()/2, 45), 10)#создаем вывод цвета в web стиле
    RGBstring.draw(win)# рисуем на форме win

    Coordstring = Entry(Point(win.getWidth() / 2, 185), 10)# создаем отображение координат
    Coordstring.draw(win)# рисуем на форме win


    while True: # цикл перереисовки формы
        time.sleep(0.1)# задержка в 0.1 с, чтобы питон не сходил с ума
        x, y = pyautogui.position()#получаем в x, y координаты мыши
        r, g, b = pyautogui.pixel(x, y)# получаем в r, g, b цвет
        ColorDot.setFill(color_rgb(r, g, b))#Обновляем цвет
        RGBtext.setText(pyautogui.pixel(x, y))#Обновляем RGB
        RGBstring.setText(color_rgb(r, g, b))#Обновляем web цвет
        Coordstring.setText(str(x)+" "+ str(y) )#Обновляем координаты
        win.flush()# Даем команду на перерисовку формы
#основной код начинается ниже.

main()#вызываем нашу функцию.


image

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

1) мало времени на определение цвета и посыл нажатия

2) цвета кружков очень неоднородные

3) незначительные отклонения в позиционировании камеры сильно мешают

Однако поковырявшись еще чуть чуть, мне в голову пришла идея захватывать не пиксели нужного цвета а изменения яркости в нужных местах т.к. эксперементы с пипеткой показали, что кружки гораздо выше по шкале R, G или B ( в зависимости от цвета) нежели фон игрового поля. В итоге я выбрал 8 точек где кружки проходят в наибольшем размере.

image

Шаг 1. Кодим распознавание кружка


Код анализатора
import time# модуль времени ( стандартный )
import pyautogui# автоматизатор ( скачивается отдельно )
import winsound#модуль для сигнала, чтобы знать, что программа запустилась ( стандартный )
import keyboard#модуль для работы с клавиатурой ( скачивается отдельно )



def analyzer():

    etalon = [pyautogui.pixel(355, 288), pyautogui.pixel(460, 200), pyautogui.pixel(600, 130),\
        pyautogui.pixel(735, 112), pyautogui.pixel(875, 109), pyautogui.pixel(1000, 145), \
         pyautogui.pixel(1139, 203), pyautogui.pixel(1260, 290) ]#массив эталонных цветов

    trigger = [0,0,0,0,0,0,0,0]#массив триггеров, инициализируем нулями



    while True:

        change = [pyautogui.pixel(355, 288), pyautogui.pixel(460, 200), pyautogui.pixel(600, 130),\
        pyautogui.pixel(735, 112), pyautogui.pixel(875, 109), pyautogui.pixel(1000, 145), \
         pyautogui.pixel(1139, 203), pyautogui.pixel(1260, 290) ] #Забираем в цикле change массив текущего состояния точек

        for nomer in range(0,8):
            if change[nomer][0] > etalon[nomer][0]+50 or change[nomer][1] > etalon[nomer][1]+50 or change[nomer][2] > etalon[nomer][2]+50:

                if trigger[nomer] == 0: #если точка изменила цвет по R,G или B больше чем на +50 и триггер прохождения выключен
                    trigger[nomer] = 1#включаем триггер прохождения
            else:
                if trigger[nomer] == 1: #проверяем не включен ли триггер прохождения
                    trigger[nomer] = 0 #обнуляем триггер прохождения
                    print("push " +str(nomer) + time.strftime(' %X'))

#основной код начинается ниже.

keyboard.wait(combination="home")#после старта ждем нажатия клавиши "Home"
winsound.Beep(1000, 100) #сигналим что программа стартанула
analyzer()# запускаем анализ


Разбор алгоритма:

  1. Кладем в массив etalon цвета фона игрового поля, с которым впоследствии будет происходить сравнение цветов массива change Строчка

      
    keyboard.wait(combination="home")

    нужна как раз, чтобы забрать эталонные цвета в момент, когда игра уже развернута и камера отцентрирована
  2. Инициализируем массив триггеров trigger. Он нам нужен, поскольку питон отрабатывает много раз, пока кругляш бежит к центру. Кругляш большой а точка в которой мы снимаем показания маленькая. То есть, для того, чтобы один и тот же кругляш мы не зарегистрировали дважды и более.
  3. Запускаем бесконечный цикл в котором мы постоянно забираем значение цветов в массив change и сравниваем цвета каждой из забранных точек с эталонными цветами

    for nomer in range(0,8):
                if change[nomer][0] > etalon[nomer][0]+50 or change[nomer][1] > etalon[nomer][1]+50 or change[nomer][2] > etalon[nomer][2]+50:
  4. Если в предыдущем IF'e мы выяснили что цвет точки с номером nomer ярче хотя бы на 50 единиц по любому из значений RGB, то проверяем зажжен ли триггер для этой точки и если нет — зажигаем

        if trigger[nomer] == 0: 
                        trigger[nomer] = 1
  5. Если же цвет в постоянно обновляемом change соответствует эталонному цвету, то тут два варианта. Либо все тихо и кружка еще нет, либо кружок только что съехал дальше с проверяемой точки, что и является сигналом для нажатия кнопки. Определяемся мы в итоге по состоянию триггера. Если триггер был зажжен — значит кругляш уехал. Обнуляем триггер и пока условно нажимаем кнопку.

                    if trigger[nomer] == 1: 
                        trigger[nomer] = 0 
                        print("push " +str(nomer) + time.strftime(' %X'))

Шаг 2. Запускаем и тестим


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

image


Слева — то, что выдал вывод питона, справа — то, что записал я, просматривая видео в замедленном режиме. Как видите есть погрешности в виде лишних нажатий 6 и 0 — это чертовы снежинки, которые никак нельзя убрать. Штука в том, что для исходной цели, непрерывного сбора подарочков, нам не нужен 100% счет, игра прощает игроку довольно много ошибок. Если бы это было не так, то просто нужно было бы ввести дополнительную проверку на белый цвет.

Шаг 3. Кодим нажималку кнопок через потоки


Тут собственно ничего заумного нет. Мы получаем номер точки и через 2 секунды нажимаем кнопку. Почему через 2 секунды? Потому, что кругляш с момента когда мы его засекли доезжает до середины примерно за 2 секунды. Небольшая хитрость тут заключается в том, что нажимать кнопки нужно независимо друг от друга. Мы не можем ставить исполнение программы на паузу применив классический sleep() т.к. все собьется да и вообще кругляши летят достаточно быстро. Можно организовать очередь или воспользоваться потоками, что, как мне думается, является более изящным решением( если конечно питон и много потоков не тормозят на вашем ПК ).

Добавляем в код

from threading import Timer

и сам обработчик отложенного нажатия

def delaypress(keynum):
    if keynum < 4:
        keynum +=1
    else:
        keynum +=2
    t = Timer(2, keyboard.send, args=[str(keynum)])
    t.start()

Если на вход поступает номер точки 0-1-2-3 нажимаем через 2 секунды номер точки + 1, если же поступает 4-5-6-7, то нажимаем через 2 секунды номер + 2 ( т.к. кнопка 5 не задействована в мини игре )

Конечный вид кода:
import time# модуль времени ( стандартный )
import pyautogui# автоматизатор ( скачивается отдельно )
import winsound#модуль для сигнала, чтобы значть, что программа запустилась ( стандартный )
import keyboard#модуль для работы с клавиатурой ( скачивается отдельно )
from threading import Timer#импортим таймер из модуля потоков ( стандартный )

def delaypress(keynum):
    if keynum < 4:
        keynum +=1
    else:
        keynum +=2
    t = Timer(2, keyboard.send, args=[str(keynum)])
    t.start()

def analyzer():

    etalon = [pyautogui.pixel(355, 288), pyautogui.pixel(460, 200), pyautogui.pixel(600, 130),\
        pyautogui.pixel(735, 112), pyautogui.pixel(875, 109), pyautogui.pixel(1000, 145), \
         pyautogui.pixel(1139, 203), pyautogui.pixel(1260, 290) ]#массив эталонных цветов

    trigger = [0,0,0,0,0,0,0,0]#массив триггеров, инициализируем нулями



    while True:

        change = [pyautogui.pixel(355, 288), pyautogui.pixel(460, 200), pyautogui.pixel(600, 130),\
        pyautogui.pixel(735, 112), pyautogui.pixel(875, 109), pyautogui.pixel(1000, 145), \
         pyautogui.pixel(1139, 203), pyautogui.pixel(1260, 290) ] #Забираем в цикле change массив текущего состояния точек

        for nomer in range(0,8):
            if change[nomer][0] > etalon[nomer][0]+50 or change[nomer][1] > etalon[nomer][1]+50 or change[nomer][2] > etalon[nomer][2]+50:

                if trigger[nomer] == 0: #если точка изменила цвет по R,G или B больше чем на +50 и триггер прохождения выключен
                    trigger[nomer] = 1#включаем триггер прохождения
            else:
                if trigger[nomer] == 1: #проверяем не включен ли триггер прохождения
                    trigger[nomer] = 0 #обнуляем триггер прохождения
                    #print("push " +str(nomer) + time.strftime(' %X'))#заменяем печать на вызов нажималки
                    delaypress(nomer)


#основной код начинается ниже.

keyboard.wait(combination="home")#после старта ждем нажатия клавиши "Home"
winsound.Beep(1000, 100) #сигналим что программа стартанула
analyzer()# запускаем анализ


Шаг 4. Гребем профит


image

Заключение и ссылки


А теперь, как и обещано, расхваливаю питон( надеюсь достаточно обоснованно ).

  • Питон отлично подходит людям с базовыми знаниями в области программирования и гуглинга для решения интересных задач.
  • Реально юзер френдли язык. Лично по моим ощущениям синтаксиса меньше раза в три и нет идиотского количества ошибок, как в других языках, даже при написании небольших программ.
  • Отличная экосистема. Если вы знаете, как сформулировать вопрос гуглу, вы с большой долей вероятности найдете или готовое решение или инструмент, позволяющей сделать, то, что вы хотите.
  • Нет танцев с бесконечными перекомпиляциями. На современных ПК небольшие программки конечно компилятся быстро, но все равно это раздражает если вы учитесь и приходиться пересобирать проект десятки раз.
  • Документация. По простоте, понятности и лаконичности ближайший аналог видел только у PHP.
  • В питоне прослеживаются черты линукс философии. Даже установка новых модулей легка и приятна и не вызовет у вас трудностей если вы освоили какой нибудь apt или yum
  • Питон удобен для создания всяких хаков и автоматизаций в играх, особенно тех, где требуется частая модификация. Если статья хорошо зайдет — обязательно расскажу как просто на питоне писать в память чужого процесса, делать zoom/speed хак и управлять всем этим безобразием с клавиатуры.

Pyautogui документация
Graphics документация
Документация по модулю keyboard

Если есть интересные идеи для хаков на питоне — пишите в личку.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 41
  • +4
    Так держать!
    Код не программиста, но для «Инженера» просто здорово.

    Да, а в первом абзаце заключения, я бы просто поставил точку вот после этих слов:
    Питон отлично подходит людям

    • +8
      • Поручик, вы и на питоне программировать можете?
      • Могу-с, только ноутбук постоянно соскальзывает.
      • +1

        Это же великолепно!!!
        Раньше я для автоматизации рудиментарного бота (зрение+кноподав) пользовался несложным AutoIt — тоже могу порекомендовать.

        • 0
          Пробовал. Штука классная, но питон на порядок богаче по возможностям. В библиотеке pyautogui например есть locateOnScreen('вырезанная_картинка.png') которая позволяет в автоматическом режиме рапознавать изображение на экране и возвращает центр его координат. Таким образом можно например решать простые головоломки в играх или обходить каптчу самописной защиты в LineageII
        • 0
          Ботов для игр проще писать на базе чтения памяти с помощью win32api readProcessMemory или MmCopyMemory.
          • +1
            Естественно. Это как раз и будет материалом следующей статьи. Просто на питоне это делать легко и приятно даже для новичков и я сильно удивлен, почему его еще активно не используют под это дело.
            • 0
              Ну почему ж — в наше время раньше был популярен перл, просто он вдруг стал сложным для большинства :)

              Ботик для РО
              • 0
                буду очень ждать. использую struct, ~winapi(readprocessmemory) и ctypes. и пока код не очень красивый.
                другой вопрос, как выполнять такие задачи параллельно? допустим, при работе Pyautogui нельзя пользоваться компьютером. ну не запускать же под каждую копию игры виртуалку.
                • 0
                  да, я хотел бы видеть в статье подробный разбор readprocessmemory(processHandle, addr, buffer, len(buffer), ctypes.byref(bytesRead)) как при этом читать строки, юникод, байты?
                  к примеру, где-то для buffer используют ctypes.create_string_buffer(bytes), а где-то ctypes.c_ulonglong()
                  • 0
                    Готовлю материал. Просто разобрать нужно на каком то интересном примере, а не сферический код в вакууме да еще, чтобы было понятно хотя бы 80% аудитории хабра. Подготовка такой статьи довольно времязатратная штука.
                • 0
                  а такое разве не будет палить античит?
                  • +11

                    Можно через Meltdown.

                    • +3
                      Два чая этому господину!
                      • 0
                        Что будет заметно дольше без знания точных адресов, правда.
                      • 0
                        Практически для любой популярной онлайн игры есть обходы ее античитов в паблик доступе. Если нет в русском сегменте, то точно можно найти в англоязычном. Как говориться волков бояться — в лес не ходить. А вообще процесс python.exe исполняющий ваш код наверняка выглядит менее подозрительным, нежели какой нибудь Xc7$smkT.exe да еще и инжектящий в процесс игры свою библиотеку.
                        • 0
                          Название процесса звучит как Dr.Web CureIt (правда не уверен насчет инжектов)
                    • 0
                      А если такое дело пошло, на каком стеке и какими тулзами проще всего писать эффективных(полноценных) ботов для игр?
                      • +1
                        Исследование игры на нижнем уровне и написание под нее бота — штука комплексная. Есть замечательная книга на эту тему которая на 90% описывает то что вам нужно. gamehacklab.ru/topic/4834-утекла-книга-гейм-хакинг-разработка-автономных-ботов-для-онлайн-игр Найти ее можно и в pdf правда на английском. Если такие вопросы — рекомендую начать с вещей попроще, вроде поиска нужных значений в памяти и программного чтения/записи в них. Например на том же питоне.
                    • –7
                      После того, как попробовал писать на питоне, слег в больницу с диабетом
                      • 0
                        Классная шутка, же. Чего сообщество не оценило? Видно, нужно было написать «с синтактическим диабетом»
                      • +1
                        интересно получилось, как-то давно делал похожее на delphi, для LAII, играл на пиратке с хай рейтом, суть была в том чтобы банки CP использовались автоматически. Кто играл на пвп серверах думаю поймет.
                        • 0
                          «Спам ГЦП банок». С тех пор придумали игровые мыши с макросами и доп.клавишами)
                          P.S.: тоже делал, только для спама подходило плохо, а вот циклить макрос /nexttarget /attack /delay 15 /pickup /pickup /pickup получалось замечательно. Ставишь в центр маленькой комнаты в катах и машинка фармит камни за тебя)
                        • 0
                          Делал подобную конструкцию для другой игры, тоже для новогоднего эвента и тоже ради спортивного интереса… Только использовал связку Python + OpenCV. Нарезал эталонных изображений, которые бот искал на экране и кликал по ним автоматически. На контрастных объектах отрабатывает с довольно высокой точностью.
                          • +2
                            Главный недостаток Python'а в плане ботостроения — совершенно кошмарная работа с кодировками текста. Как только вы начинаете искать строки в памяти процесса и конвертить их, скажем, из cp1251 в utf-8, вы проклянёте Python. Все эти долбанные декодеры с энкодерами никогда не работают как надо, да к тому же любая ошибка закончится километром бессмысленных логов, увенчанных UnicodeDecodeError, и во всём этом мусоре не будет ни малейшего намёка на строку, реально вызвавшую ошибку.
                            • +1

                              В 3-ей версии Python "Все эти долбанные декодеры с энкодерами" всегда работают как надо. А километровые логи на много короче чем в Java и слева указывают имя модуля, имя функции, а справа номер строки для более полного понимания в каком месте произошла ошибка. Или Вы ожидаете от ЯП подобного:
                              Error in line 13 you meant print() instead pirnt()

                              • 0
                                «Error in line 13 you meant print() instead pirnt()»
                                clang и GCC вроде в последних версиях так и делают
                            • 0
                              Если вы «труъ» программист и готовы брызжа слюной доказывать, что питон фигня и новичков сразу нужно макать в ручное управление памятью, яки младенца в святую воду — можете смело закрывать статью.

                              Как бы между Python и ручным управлением памятью есть и промежуточное звено: языки с автоматической сборкой мусора.


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

                              А C#, Kotlin да и другие языки не подходят?


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

                              Очень спорное утверждение. Как раз таки в Python ошибок может быть только больше из-за его динамической природы.


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

                              Опять-таки. А к другим языкам это не относится?


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

                              Помимо Python вы знаете только C++?


                              Документация. По простоте, понятности и лаконичности ближайший аналог видел только у PHP.

                              Да куча документации хорошей и разной по популярным языкам.


                              В питоне прослеживаются черты линукс философии. Даже установка новых модулей легка и приятна и не вызовет у вас трудностей если вы освоили какой нибудь apt или yum

                              nuget для C#, maven для Java.


                              Питон удобен для создания всяких хаков и автоматизаций в играх, особенно тех, где требуется частая модификация.

                              Какая модификация?

                              • +6
                                Если вы «труъ» программист и готовы брызжа слюной доказывать, что питон фигня и новичков сразу нужно макать в ручное управление памятью, яки младенца в святую воду — можете смело закрывать статью.
                                Как бы между Python и ручным управлением памятью есть и промежуточное звено: языки с автоматической сборкой мусора.

                                Сие было небольшим троллингом программистов, которые отрицают, что не все языки подходят для освоения юными падаванами и кричат что именно их язык нужно учить потому что он самый[хардкорный, массовый, энтерпрайзный, кошерный, ...] да еще и литературы вдобавок насоветуют а ля «паттерны проектирования» или опусов Кернигана и Ричи. Это ведет к скорейшему забиванию на идею что нибудь попрограммировать.

                                А C#, Kotlin да и другие языки не подходят?

                                На шарпе переделывал инъектор для игры Rust, опять же при помощи гугла и советов коллеги — то еще удовольствие если с языком не работаешь каждый день. Так же, если на питоне понравилась программка или модуль — то ты открываешь, изучаешь и копируешь нужный код. В c# для подобного пришлось качать net reflector и прогонять прогу через деобфускатор de4dot. Я думаю не стоит тут упоминать как выглядит код после деобфускации, кто ковырял сам знает.
                                Очень спорное утверждение. Как раз таки в Python ошибок может быть только больше из-за его динамической природы.

                                Возможно для больших и сложных проектов это так, но у меня есть только опыт написания небольших программок под собственные нужны и он говорит об обратном.
                                Опять-таки. А к другим языкам это не относится?

                                На мой, достаточно субъективный, взгляд накладывается опыт разбирательств с другими языками. Питон сообщество нацелено не только на профессионалов, вот в чем его плюс. Возможно, если вы опытный программист, вы не заметите разницу в общении на форумах или в подаче документации, но для начинающих важно чтобы объяснялось для их уровня. И да, никто не будет делать на c# или java программки для системного администрирования,
                                а на питоне будут. Это и создает ту экосистему для людей-не-программистов.
                                Помимо Python вы знаете только C++

                                А кто сказал что я знаю python и с++? Я знаю базовые для всех языков конструкции и как пользоваться гуглом. Дополнительный синтаксис осваивается за пару часов ( если это конечно не lisp или брэйнфак ). Это как раз та фишка о которой я и говорил в статье — питон не нужно хорошо знать чтобы решать на нем задачи.
                                Да куча документации хорошей и разной по популярным языкам.

                                Опять же с точки зрения профессионального программиста да, а с точки зрения не программиста вопрос очень спорный. Отписал выше.
                                nuget для C#, maven для Java

                                Не спорю. Тут это просто плюс, по сравнению с языками, в которой таких систем нет.
                                Какая модификация?

                                В играх отвратительно часто встречаются апдейты меняющие статические адреса и указатели, хранящие скорость, коэффициент разброса оружия или еще какую нибудь интересную переменную. Или например ввели в игре временное изменение и кликер тыкает уже не туда, куда ему положено.
                              • –1
                                Большое спасибо за статью, дали пищу для размышлений :) Плюс пока не могу поставить — карма низковата, но считайте этот плюс плюсом в свою личную карму ;)
                                Я немного поворчу, если позволите
                                мой быдлокод будет резать вам глаз

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

                                расхвалить питон и показать еще не освоившим, что с ним может делать человек-не-программист

                                Именно это как раз важно. Это как выучиться на сварщика, но работать/подрабатывать в оркестре барабанщиком (и делать это хорошо).
                                Статья хорошая, осталось чуть-чуть подтянуть правописание (судя по комментариям, Вы умеете писать грамотно, что не очень часто встречается — просто не торопитесь с публикацией)).
                                Всё, перестаю ворчать.
                                • 0
                                  Отлично! Хочу ещё python магии. )
                                  • 0
                                    Мы не можем ставить исполнение программы на паузу применив классический sleep() т.к. все собьется да и вообще кругляши летят достаточно быстро.
                                    Что-то туплю… Почему собьется? По поводу скорости: а sleep(0.01) не пробовали?
                                    • 0
                                      Смысл в том, что кругляш едет до центра около 2-х секунд и кнопку нужно нажимать через 2 секунды, после того как его засекаем программно. то Есть если поставить time.sleep(2) а потом нажать кнопку, кнопка то нажмется, но в эти 2 секунды программа не будет ловить другие кружки а тупо ждать.
                                    • 0
                                      А не подскажете модуль (не нашел, мб плохо искал) который анализирует звук исходящий из игры? И при помощи которого можно сделать специальные триггеры на определенный звук? Как выше в комментариях написано было, например,
                                      locateOnScreen('вырезанная_картинка.png')
                                      • 0
                                        Занятная статья. Также, хотелось бы увидеть пару слов о защите в таких играх.
                                        • 0
                                          У меня накопилось некоторое количество опыта по обходу защит и даже кое какие свои наработки, но боюсь ответ значительно превосходит формат комментария. Вроде статья неплохо зашла, думаю и на тему защит напишу со временем.
                                        • 0
                                          Поздравляю, вы изобрели велосипед. OpenCV поможет его сильно проапгрейдить.
                                          Сам кодю на питоне, но без openCV в таких задачах повеситься можно.
                                        • 0
                                          Арбитраж!))) А вообще понравилась, интересная идея и доведение её на результата
                                          • 0
                                            Ребят, а кто имеет ботов для телеграмм игр? тот же Chat Wars?

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