Pull to refresh

История одного покерного бота

Reading time6 min
Views48K
Сейчас возможность написания покерного бота уже не вызывает сомнений (есть даже серия статей в журнале Хакер), а вот в 2008 году все было не настолько очевидно и все что можно было найти — одна единственная статья на английском языке, которая описывала лишь общие идеи, которое так и не прижились в нашем проекте. Но даже сейчас мало кто будет делится успешными историями.
В данной статье я опишу наш опыт разработки бота, который действительно тестировался в реальных покер румах и даже научился играть и не проигрывать. Те, кто собрался писать своего бота — найдет в статье интересные вещи и пути облегчения себе жизни. Кому интересно — добро пожаловать под кат.

Как все начиналось


Идея написания бота посетила моего друга, который поделился ей со мной и с моим соседом по общаге, собственно и сам друг тоже был с общаги.
Роли были разделены следующим планом:
• Разработчик логики (автор идеи)
• Разработчик парсера (сосед)
• Разработчик глаз и рук (я)
Было решено писать бота для лимитного холдема (автор идеи на тот момент зарабатывал некоторые деньги играя именно в этот тип игры)
В таком составе и с такими ролями мы двинулись в бой. В итоге у нас получилось 3 итерации разработки с перерывами между ними в месяца 3-4, о которых я и постараюсь ничего не забыв рассказать поподробнее.

Итерация 1


Какое это было время. Три зеленых студента начали думать. Нужны были инструменты, изначально выбор был таким:
• C++ — Логика игры
• VB.Net — Все остальное
Но спустя немного часов разработки мы решили, что нужно учить C# и вместо Бейсика стали использовать его.
К сожалению ничего о тех мозгах, которые сидели в DLL на C++ рассказать не могу, да и уже никто не может (просто напросто уже никто помнит), помню только, что там был кромешный ад, в котором даже автор путался и иногда удивлялся, что что-то случайно работает/не работает.
Выбранный нами покер рум для испытаний располагал отличными чатом, с которого было решено брать информацию для анализа происходящего. Этим анализом и занялся мой сосед.
Мне же нужно были научиться отдавать ему чат вовремя, оставалось понять, когда это вовремя наступает.
Итак, первые вопросы которые необходимо было решить были:
• Как найти среди всех окон системы нужные?
• Как понять, что пора ходить?
• Как ходить?
• Как получить чат?
Поподробнее о решении проблем ниже (есть ощущение, что именн в таком порядке я их тогда и решал).

Как понять, что пора ходить?

Я тогда что-то слышал про WinApi, но что это за зверь и как его приучить — я был не в курсе. Очень скоро я узнал, что по таинственному хендлу можно очень много узнать об окне и много всего сделать, также я узнал что за окном можно неплохо следить. Вооружившись Spy++, я окунулся в мир тогда еще простого узнавания хендла путем наводки крестика на окно)))
Курение манулов позволило мне узнать, что можно спросить цвет точки на рабочем столе и что можно сказать системе, что мышка кликнула кнопкой.
Решение задачи стало очевидным:
1. ищем точки по цвету которых можно узнать что кнопки появились (т.е. Пришло время ходить)
2. получаем координаты окна,
3. складываем с координатами точки для определения
4. постоянно делаем окно активным и проверяет цвет точки
5. Если цвет стал нужным — пора ходить

Как получить чат?

Уже умея использовать Spy++ было легко найти хендл. Снова покурив манулы я понял как отправить в окно Ctrl+A, Ctrl+C. Далее средствами C# получал содержимое буфера. Чат есть.

Как ходить?

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

Как найти среди всех окон системы нужные?

Эта задача оказалась самой сложной — ее я долго не мог решить, пока не обратился к своему преподавателю (спасибо Черносвитов А.В.) по C#/C++ и он вспомнил функцию EnumWindowsProc или как-то так. С помощью Spy++ поискал особенности окна, но в итоге такой особенностью оказался заголовок, который кстати тоже можно получить по хэндлу окна, после чего используя EnumChildWindowsProc (перебор всех дочерних окон) находился чат.

Итоги итерации 1

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

Итерация 2


Спустя несколько месяцев решили писать снова, для ускорения процесса мы решили снести компьютеры в одну комнату и работать вместе там.
В ходе данной итерации было осуществлено:
• Переезд на один язык – мы переехали полностью на C#.
• Переход на анлим турниры
• Прикручено много столов
• Попробовано использование системных хуков для определения, что пора ходить
• Улучшено получение чата
• Улучшен механизм совершения хода

Переход на анлим турниры

Логика была переписана на C# и были использованы стартовые таблицы для игры в турниры с сайта pokerstrategy.com, что позволило сделать достаточно чистую и понятную логику. Здесь же были попытки сделать конфигуратор логики (мы хотели продавать бота на сторону, чтобы каждый писал сам себе логику), но мы решили, что это утопия и прекратили развитие идеи.

Прикручено много столов

Вместе с новой прозрачной логикой добавили и возможность игры на нескольких столах. Реализация такой возможности была крива — по очереди каждый стол на первый план, проверка цвета на необходимость хода — если пора ходить, то ходим. Тем не менее, такая схема работала, и это было победой. Но теперь бот блокировал комп совсем и намертво.

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

К этому времени я уже был достаточно силен, чтобы начать копаться с системными хуками Винды. Так как из C# не повесить системных хуков на приход сообщений окну — был использован проект с CodeProject (http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx), который состоит из DLL и логики на C# запускающей эту DLL и получающую информацию от нее. Хуки позволяли не делать кучу переключений между окнами для определения хода, но отловить точный порядок сообщений, после который необходимо ходить так и не получилось, плюс хуки тормозили систему и в итоге от хуков отказались.

Улучшено получение чата

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

Улучшен механизм совершения хода

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

Итоги итерации 2

После этой итерации получился бот, играющий на многих столах в турнирный холдем с прозрачной логикой (кстати таблица предложенная на PokerStrategy.com проигрышна, если полностью следовать ей и не думать больше). Бот уже мог оставлять небольшой шанс хоть как-то работать хозяину компьютера.

Итерация 3


К третьей итерации нас дошло двое, мой сосед выпал из проекта и его часть кода переписывалась с нуля (было трудно поддерживать чужой код, тем более что необходимо было его существенно развивать). Во время третьей итерации мы достигли:
• Использование нового механизма определения времени хода
• Использование нового механизма получения чата
• Использование новой логики

Использование нового механизма определения времени хода

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

Использование нового механизма получения чата

Чат покер рума имел класс InetnetExplolerClass или как-то так. К этой итерации я нашел способ извлечения текста из таких объектов и код на VB.Net, который работал. Код был переписан на C# и теперь получение чата было без каких либо копирований в буфер и было более стабильно.

Использование новой логики

Стало понятно, что для турниров нужен эквилятор и расчет ICM модели, и мы начали пытаться это получить. Написанный моим напарником эквилятор мог просчитывать 5000 игр в секунду, в то время как Equiliator от PokerStrategy.com мог 1500000 на той же конфигурации – это был провал и нужно было что-то с этим делать.
Однажды сидя ночью, я зашел в папку с файлами софта PokerStrategy.com (Equiliator, ICM Trainer) и обнаружил, что они написаны на .Net. Это меня несказанно обрадовало и последующие 2 дня я потратил, чтобы запустить этот софт у себя под дебагом, но в итоге мы могли полностью смотреть как использовать библиотеки этой компании и успешно научились ими пользоваться.
В итоге наш бот перед ходом считал свои шансы быть в выигрыше, а в крайней стадии турниров использовал чистый ICM, что давало ему определенные преимущества.

Итоги итерации 3

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

Итоги


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

Если у Вас возникнет желание писать своего бота – я надеюсь, что найденные нами решения позволят Вам быстрее его написать.
Tags:
Hubs:
+15
Comments74

Articles

Change theme settings