Как сделать бота для игры

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

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

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

Введение

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

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

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

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

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

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

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

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

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

Перемещение указателя мыши к нужной точке:
(выполнено не очень аккуратно, обещаю исправиться :-))

Мануал юзера

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

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

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

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

Источник

Пусть компьютер сам принимает решение или пишем ИИ для игры вместе

Вы когда-нибудь задумывались о том, насколько просто написать свой искусственный интеллект, который сам будет принимать решения в игре? А ведь это действительно просто. Пусть для начала он принимает случайные решение, но позже вы можете его воспитать, научить анализировать ситуацию, и тогда он станет принимать осознанные решения. В этой статье я расскажу, как я писал своего бота, а также покажу, как вы за несколько минут можете написать своего. Наш компьютер будет играть в клон игры Трон, а точнее в ту часть, где нужно на мотоцикле победить врагов.

Как сделать бота для игры. Смотреть фото Как сделать бота для игры. Смотреть картинку Как сделать бота для игры. Картинка про Как сделать бота для игры. Фото Как сделать бота для игры
Под катом gif-файлов мегабайт на 10.

Об игре

В игре вы управляете мотоциклом, который оставляет за собой стену из света. Игровое поле ограничено, а у соперников такие же мотоциклы. Мотоцикл едет постоянно, вы лишь можете поворачивать. Свободное место на поле кончается, и избегать препятствия становится сложнее. Побеждает тот, кто дольше всех продержится. Клон игры я сделал браузерным многопользовательским с использованием node.js и socket.io. Управление из двух кнопок – поворот влево и поворот вправо.

Интерфейс бота

При поступлении от сервера команды обновления данных мотоциклов (было совершено их передвижение) я проверяю, есть ли у меня вообще подконтрольный мотоцикл, не столкнулся ли он еще и был ли он перемещён, и, в случае успеха, я вызываю основной метод для работы ИИ — update().
Интерфейс готов, теперь можно добавить сам ИИ.

Искусственный интеллект

Когда я решил написать бота, я понятия не имел, как это можно сделать. Я попробовал очень простой код:

Поведение было примерно таким:
Как сделать бота для игры. Смотреть фото Как сделать бота для игры. Смотреть картинку Как сделать бота для игры. Картинка про Как сделать бота для игры. Фото Как сделать бота для игры

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

Но хотелось, чтобы он жил как можно больше. Я стал искать информацию о том, как пишут ИИ к играм. Нашел статьи, которые описывали разные подходы. Но я искал что-то чрезвычайно простое. Я нашел на хабре в одной из статей про бота для игры вроде Zuma упоминание волнового метода. Он же алгоритм Ли. Мне он показался очень простым и подходящим. Это алгоритм поиска кратчайшего пути из одной точки в другую по полю, где клетки могут быть либо свободными, либо занятыми. Суть простая. Мы начинаем из точки назначения, присваиваем ей значение 1 и помечаем все соседние свободные клетки цифрой на единицу больше. Затем берём все соседние свободные помеченных и снова помечаем на единицу больше. Так расширяемся на всё поле, пока не дойдем до точки назначения. А путь строим поиском из соседних по уменьшению числа, пока не дойдем до 1. Я смотрел алгоритмы поиска кратчайших путей в графах, но этот мне показался наиболее подходящим.

Я перенёс алгоритм копипастой из страницы в вики, дал ему имя BotSocket.prototype.algorithmLee. Для поля я создал сначала объект battleground, в котором при каждом обновлении помечал занятые точки с их координатами. А в алгоритме Ли сводил это поле к такому же, но с шагом 1.

Нужно было как-то определять точку назначения. Я решил выбирать её случайно через определенные интервалы времени. Сделал метод для поиска случайной свободной точки на поле:

Теперь я мог переписать update:

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

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

Бот на стороне клиента

Я решил попробовать перенести бота на клиентскую часть. Так как проект на node.js, я могу использовать написанный код для бота и на стороне клиента. Для этого я расширил BotSocket отдельным клиентским файлом, который переопределял методы emit() и control(), чтобы правильно взаимодействовать с сервером без ссылки на объект game.
Локально всё работало отлично, а после деплоя на удалённый сервер была какая-то странная картина:
Как сделать бота для игры. Смотреть фото Как сделать бота для игры. Смотреть картинку Как сделать бота для игры. Картинка про Как сделать бота для игры. Фото Как сделать бота для игры

Долго думая, я понял, что дело в задержке. Бот отправлял команду поворота, но она доходила после обновления его позиции на сервере, отчего он часто не мог попасть на прямой путь к желаемой точке. Но я хотел нормального бота на клиентской стороне. Поэтому решил учитывать задержку. Для этого написал снова расширение BotSocket. Статья получается длинной, так что опишу основные решения. Перед вызовом алгоритма Ли вместо текущей точки я подставлял прогнозируемое положение с учетом текущего положения и направления, а так же множителя задержки. Множитель задержки – это число, во сколько раз превосходит задержка частоту обновления положения на сервере. Предсказание будущей точки мне еще понадобилось в методе moveToPoint().

Предсказание работало, если играл один. Но если были другие участники, то бот не учитывал это и направлял туда, где через некоторое время уже проехал другой игрок. Для решения этой проблемы я изменил метод, который помечает клетки поля занятыми. Я стал их помечать занятыми в некотором радиусе движения мотоциклов. Радиус зависит от множителя задержки.
Предварительно я снабдил бота функциями отладки, который рисовали на поле желаемую точку и занятые точки. Моя версия клиентского бота с учетом задержки теперь двигается так:
Как сделать бота для игры. Смотреть фото Как сделать бота для игры. Смотреть картинку Как сделать бота для игры. Картинка про Как сделать бота для игры. Фото Как сделать бота для игры
Мой красненький, остальные серверные.

Самое важное – попробуйте сделать бота сами

Основная цель этой статьи – пробудить интерес к написанию бота. Я сделал много, чтобы победить вашу лень. Для этого я добавил возможность подгружать свой собственный скрипт с ботом, который будет расширять мой базовый клиентский класс. Зайдите на проект и нажмите на текст «Show options for room with your own bot», а затем на кнопку «Create room for test your own bot». Будет создана комната, где можно легко применять ботов, по умолчанию вашим ботом будет бот без учета задержки. Теперь настало время для вашего кода.
Два простых варианта для использования вашего кода в деле, используйте любой:

Если вы определились с методом ввода вашего кода, попробуйте переопределить методы класса BotSocket. Для начала самое простое:

После этого пересоздайте объект botSocket, введя

При этом код на странице сам пересоздаст и заполнит объект. Этим вы измените стандартное поведение бота на случайное. А дальше уже дело для вашей фантазии или глубоких знаний.
Вы так же можете подключить скрипт моего улучшенного бота с учетом задержки, вставив в url для бота https://raw.github.com/rnixik/tronode-js/master/public/javascripts/MyBotSocketClient.js

Заключение

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

Если у вас нет под рукой node.js, вы можете воспользоваться развернутыми мной приложениями:

1) tronode.livelevel.net — самая дешевая VPS на DigitalOcean,
2) tronode-js.herokuapp.com — бесплатная виртуальная единица на Heroku.

Первый, скорее всего, первым может не справиться с нагрузкой, а второй на некоторых компьютерах сбрасывает socket.io-транспорт в xhr-polling, из-за этого игра очень сильно лагает.
Если вы хотите узнать больше, о том, как я программировал игровую логику, то можете прочитать здесь. Там же о развертке node.js и немного о графической части.

Если у вас нет аккаунта на хабре, то задать вопросы или прислать свои интересные предложения можете мне на почту dev@1i1.be.

Источник

Пишем бота для MMORPG с ассемблером и дренейками. Часть 0

Содержание
1. Выбор способа реализации внедрения (немного теории)
2. Инструментарий
3. Поиск точки внедрения

Итак со способом разобрались, инструментами обзавелись, теперь нам необходимо понять, куда внедрять наш код.
При отрисовке с помощью D3D создается виртуальный объект Direct3D device, который по сути представляет собой VMT(виртуальная таблица методов, которая является указателем на указатель на таблицу методов D3D). Это таблица хранит, опять же, указатели на методы Direct3D, например BeginScene, EndScene, DrawText и т.д. Нас в данном случае интересует только EndScene, т.к. Direct3D device создается в единственном экземпляре, то нам нужно получить указатель на него, а затем получить указатели на таблицу. Опять же нам необходимо определить какой D3D используется в клиенте игры и т.к. вариантов у нас 2 (DX9 и DX11), то решить эту проблему можно простым перебором. Для этого мы и будем использовать SlimDX.
В коде processMemory.Read и processMemory.ReadBytes обертки стандартной ReadProcessMemory из kernel32.dll
Проверка на DX9:

Откуда 0xA8. Если открыть d3d9.h и найти EndScene метод, то вы найдете 42 ой по счету в интерфейсе IDirect3DDevice9, а одна функция в архитектуре х86 адресуется 4мя байтами, получаем 42*4=168, а это и есть 0xA8.
Все это необходимо обернуть в try/catch и если вылетела ошибка, значит нам нужно пробовать D3D11 и тут все немного сложнее, нам нужен не EndScene, а SwapChain, он находится по индексу 8, т.е. 8 * 4 = 32 = 0х20:

Все это опять необходимо опять же обернуть в try/catch. В случае неудач обоих попыток получить адрес функции D3D возможно изменились смещения либо у вас не D3D9 или D3D11.
Итог: У нас имеется адрес функции EndScene D3D и опкоды этой функции.
Что с ними делать и как внедрить свой код я возможно расскажу в следующих частях, а пока голосуйте, осмысливайте код выше, гуглите, яндексуйте, бингуйте, яху. спрашивайте в коментариях и читайте документацию по ассемблеру, будет полный хардкор и дренейки!

Источник

Пишем бота для онлайн-игры на 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 нужна, чтобы через консоль выключить бота.

Источник

Написание бота для флэшевой игры

Как сделать бота для игры. Смотреть фото Как сделать бота для игры. Смотреть картинку Как сделать бота для игры. Картинка про Как сделать бота для игры. Фото Как сделать бота для игры

Зачем?

О лазерной коррекции зрения я подумывал давно, и вот, наконец, решился на процедуру. После недолгого изучения рынка (живу в Питере) выяснилось, что цены по городу везде примерно одинаковые, и заниматься медицинским туризмом смысла тоже нет (в Мск ненамного дешевле). Впрочем, оказалось, что на операции можно заметно сэкономить, т.к. одна из клиник предоставляет разветвлённую систему скидок на свои услуги.

Скидки ветеранам и пенсионерам меня, ясное дело, не интересовали. А вот необычной акцией «поиграй во флеш-игру на нашем сайте и конвертируй набранные очки в скидку» я решил воспользоваться. Подкатом описание процесса.

Вообще идея сперва изумила своей абсурдностью – вроде как считается, что компьютерные игры вредят зрению, и тогда акция похожа на «вычерпай из подвала 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. Потом табулятор включался, печатал колонки, потом — бац, бац, бац — вычислял арктангенс автоматически путем интегрирования и составлял всю таблицу за одну операцию.

Абсолютно бесполезное занятие. Ведь у нас уже были таблицы арктангенсов. Но если вы когда-нибудь работали с компьютерами, вы понимаете, что это за болезнь — восхищение от возможности увидеть, как много можно сделать. Френкель подцепил эту болезнь впервые, бедный парень; бедный парень, который изобрел всю эту штуку.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *