Я делаю браузерную карточную игру по своей вселенной, «Хроники Варлодов». У соперника три уровня: Новобранец, Ветеран и Полководец. Полководец самый умный, перед каждым ходом он доигрывает партию до конца много раз и выбирает ход с лучшей долей побед. И в какой-то момент этот умник стал проигрывать Новобранцу, который кладёт карты почти наугад. В 58% партий.
Расскажу, как такое вышло, и ещё про пару граблей.
Карточная дуэль, три раунда, нужно выиграть два. На старте 10 карт в руке, между раундами добираешь всего две, так что каждая карта на счету. Поле делится на три ветви: Сталь, Разум и Скрытность. Они бьют друг друга по кругу, как камень, ножницы, бумага. За ход можно положить карту, спасовать или вызвать чужую карту на поединок. Есть карты рубашкой вверх: например, Провал, тварь, которая прячется за коврами и съедает того, кто к ней прикоснётся. На карте подпись: «Не трогай ковёр».
В демо две стороны: орден Варлодов и Монстры армии Сарака.
Грабля первая: эвристики, подобранные под одну колоду
Первая версия Полководца была набором правил поверх Ветерана: «береги руку», «не лезь в проигранный раунд» и так далее. На пробных колодах он обыгрывал Новобранца в 71% партий. На настоящих картах Варлодов только в 55%. Правила были подогнаны под конкретные карты и ломались на других.
Поэтому я перешёл на поиск Монте-Карло: бот перебирает свои лучшие ходы и для каждого много раз быстро доигрывает партию до конца. Такому поиску всё равно, какая колода.
Грабля вторая: шум
Чужую руку бот не видит, поэтому вместо неё подставляет «болванки» средней силы. Первые версии раскладывали эти болванки для каждого кандидата заново. В итоге 8 прогонов на ход тонули в шуме, и «спасовать с первого хода» набирало столько же, сколько лучший ход. Полководец проигрывал Новобранцу: выигрывал только 42%.
Помогло одно: проверять всех кандидатов на одних и тех же раскладках и с одной и той же случайностью. Тогда разница между ходами видна, а шум одинаковый у всех.
Грабля третья: бот думал, что соперник тоже умный
Поиск считал соперника разумным. При перевесе в несколько очков Полководец охотно пасовал, ожидая, что соперник тоже встанет. А Новобранец не встаёт, он докладывает карту и забирает раунд. В итоге против Новобранца Полководец выигрывал реже, чем Ветеран: 54% против 66%. Теперь пас разрешён, только если его допускают простые правила Ветерана.
Баланс: Джозеф, который побеждал слишком часто
Баланс проверяют те же боты: Ветеран против Ветерана, Варлоды против Монстров, 800 партий. Норма для героя около 50% побед. Джозеф Хансвел, варлод-мститель, даже после первого ослабления выигрывал 73%. Пришлось резать второй раз: сила по ветвям была 13 и 10, потом 12 и 9, теперь 11 и 8. Дело было в его свойстве «Предвидение»: оно и так делает его поединки дешёвыми, поэтому резать пришлось силу, а свойство я оставил. Крупного дракона ростом с пятиэтажный дом тоже пришлось ослабить.
Что вынес
Бот, который подсматривает карты, меряет не ту игру. Мой видит ровно то, что игрок на экране.
Если умный бот проигрывает глупому, сначала ищи шум в собственных замерах, а уже потом ошибку в логике.
Баланс без сотен автоматических партий не сделать.
Демо уже можно погонять в браузере, название игры выше. Если делали ботов для своих игр, расскажите, на чём спотыкались вы.