Приветствую, искатели приключений!
Меня зовут Данила Бахтин, и я специалист по анализу данных отдела управления ценностью данных в Лемана Тех.

Помимо работы у меня есть несколько увлечений. Одно из самых времязатратных — настольные ролевые игры и в частности — Dungeons & Dragons (aka DnD). В настольных играх очень много зависит от бросков костей, и в какой‑то момент моя профессия проникла в мои увлечения. В своей первой статье я расскажу, как попытался подойти к анализу результатов бросков двадцатигранного кубика в партиях, в коих участвовал лично, как дата‑аналитик.


Предисловие

Решение плотно связаться с вселенной DnD было принято после выхода последнего (на момент написания статьи) 4 сезона Stranger Things.

Персонажам сериала не хватало мистического вокруг в реальной жизни и они искали острых ощущений, играя в настольные игры.
Персонажам сериала не хватало мистического вокруг в реальной жизни и они искали острых ощущений, играя в настольные игры.

В какой‑то момент жизнь свела меня с человеком, который, будучи Мастером Игры (DM), искал новых игроков для своих партий. По счастливому стечению, этим человеком был мой коллега из соседнего отдела. И вот уже почти 2 года мы собираемся небольшой дружной компанией в попытках развлечь себя приключениями на Побережье Мечей.

Но собираться стабильно нам мешали те же причины, что мешают и тебе, читатель, встретиться со старыми друзьями и бывшими одноклассниками/одногруппниками — учеба, работа, семья и банальная усталость. Совместить расписание пятерых (стандартное кол‑во игроков за столом в DnD) или более взрослых людей, даже если вы играете удаленно, достаточно сложно.

В те недели простоя, когда у нас никак не получалось найти даже двух часов, а душа требовала нового контента для вдохновления и поддержания интереса, я обращался к теперь уже многочисленным шоу на YouTube — Critical Role, Viva La Dirt League D&D и русскоязычному Подземелью Чикен Карри. И именно последнее стало причиной тому, что я в течении 10 месяцев аккуратно записывал в тетрадку результаты бросков двадцатигранного кубика. Но обо всем по порядку.


Акт I: Экспозиция и завязка

Самые известные и качественные DnD‑шоу — это высокий производственный бюджет, кастомные сценарии и... монтаж. Один выпуск длится от 1 до 3 часов, а значит сама съемка могла занять в разы больше. Только самые интересные моменты попадают в финальную версию.

Во время просмотра меня часто посещала мысль: «А что, если на кубиках на самом деле выпадают другие значения? А на мой экран попадают только подстроенные результаты, которые задуманы создателями для поддержания хода сюжета и красочности самой игры?»

Одному из ведущих в который раз удается в самый ответственный момент пройти очень сложную проверку со сложностью 18 (вероятность события - 15%).
Одному из ведущих в который раз удается в самый ответственный момент пройти очень сложную проверку со сложностью 18 (вероятность события - 15%).

Из этого сомнения родилась первая гипотеза: среднее значений бросков ведущих шоу отличается от матожидания броска кубика d20.

M(d20) = 1/20 * 1 + 1/20 *2 + ... + 1/20 * 20 = 10.5

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

Таким образом, чтобы проверить гипотезу, нужно пересмотреть около 60+ часов роликов и аккуратно все записать.

Так ли я хочу уличить кого-то во лжи?
Так ли я хочу уличить кого-то во лжи?

Нет, спасибо. Я вполне смогу найти более приятное применение такому количеству времени. Там еще новый патч у Baldur's Gate 3 вышел...

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

Сказано — сделано.


Акт II: Действия

Как я уже сказал выше, 10 месяцев я трепетно записывал все результаты бросков кубиков d20. На самом деле в DnD 20-гранный кубик — не единственный инструмент генерации случайных чисел. Всего костей 7 видов: 4-х, 6-ти, 8-ми, 10-ти, 12-ти, 20-ти и 100 — гранный. Но именно d20 используется чаще всех для бросков. Именно он определяет успех/неуспех проверок, испытаний и атак, а также ответственен за инициативу (порядок ходов персонажей) во время боевых ситуаций.

На изображении рукодельные кубики, которые я в спонтанном порыве приобрел на одном из маркетплейсов. Ни разу в реальной игре мне их бросить пока не доводилось. d20 - в центре, а d100 на самом деле - просто d10 с ещё одним нулем на каждой грани.
На изображении рукодельные кубики, которые я в спонтанном порыве приобрел на одном из маркетплейсов. Ни разу в реальной игре мне их бросить пока не доводилось. d20 - в центре, а d100 на самом деле - просто d10 с ещё одним нулем на каждой грани.

Опытные игроки в DnD, это абзац для вас! Да, я записывал вообще все броски d20: обычные, с преимуществом и с помехой. Двойные броски я записывал как два броска, не учитывая, который остается вне игры, а какой идет «в прод». Нет, я не учитывал бонусы мастерства и бонусы умений. Нет, я не учитывал, что успех проверки или атаки мог быть достигнут и при таком маленьком значении на кубики как 5 или, наоборот, быть провалом при 15. Мне не была интересна степень успешности, но только значение, выпавшее на кубике. Чистый единичный эксперимент.

За 10 месяцев и 14 партий в рамках одной Кампании Проклятье Страда мной и моими сопартийцами был совершен 947 бросок кубика d20. Прежде чем идти дальше и закрепить вторую гипотезу, которую я буду таки проверять, я познакомлю вас с ними.

Амада

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

Богдан

Воин, драконорожденный, грозный, огромного размера и с не менее огромным двуручным мечом.

Ригель

Монах, дампир, флегматичен, эксперт рукопашного боя, сначала бьет, потом снова бьет.

Скрип Сосны

Бард, кенку, безынициативен, мастер подражаний, скрытности и игры на лютне.

Соня

Варвар, оборотень, сквернословна, зачастую предпочитает импровизированное оружие верному копью.

Вот такая разношерстная компания отправилась освобождать прОклятую Боровию от тирана-вампира Страда.

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

Вторая гипотеза: среднее значение бросков кубика d20 за все партии статистически значимо отличается от матожидания 10.5 для каждого из героев и/или для савокупности их бросков.

Другими словами, я хочу проверить удачливы или нет наши персонажи с точки математики. И далее я под удачей/неудачей буду иметь ввиду больше или меньше какое‑либо значение 10.5 соотвественно. Да, успех математический и успешное прохождение испытания броском кубика d20 — это разные понятия. Но все‑таки бОльшая часть успеха состоит именно в высоком значении на кубике.

Если взять и усреднить все значения, выпавшие при 947-ми бросках за все партии, то окажется, что среднее равно 10.5026. Похоже на правду. Все канонично по ЗБЧ. Кажется, тут можно обойтись и без стат тестов. Но что будет, если мы посмотрим среднее с группировкой по персонажам?

Большинство персонажей — математически удачливы.
Большинство персонажей — математически удачливы.

Нашлись и те, кому везло чуть меньше. Среднее за все партии варьировалось от 10.16 у Ригеля до 11.07 у Скрипа. Здесь придется проверить, были ли такие «отклонения» нормой или это и есть та подозрительная удачливость.

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

Сразу видно, кто чаще атаковал и проходил проверки.
Сразу видно, кто чаще атаковал и проходил проверки.

Логичное в начале предположение о том, что вероятность отклонения от 10.5 будет выше у тех, кто бросал реже, не оправдалось. Трое из пяти игроков совершили каждый более 200-та бросков, и их средние также далеки от ожидаемого, как у игрока с чуть больше 80-тью бросками. Возможно, для достижения ожидаемого необходимо чуть больше бросков.

Настало время перейти к статистическим тестам и понять, есть ли на самом деле удача.


Для этой задачи очевидно подходит проверка двусторонней гипотезы о равенстве среднего генеральной совокупности некоторому значению методом scipy.stats.ttest_1samp. Двусторонняя также очевидно из‑за того, что мы проверяем наших персонажей на крайние степени как удачливости, так и неудачливости. За уровень статистической значимости берем стандартные 5%.

def calculate_stat_test(df,hero):
    # функция принимает на вход табличку с данными о персонажах, бросках 
    # и имя персонажа, по которому нужно рассчитать стат-тест

    # извлекаем броски конкретного персонажа
    hero_rolls = df.loc[df['player'] == hero].d20_roll

    # задаем ожидаемое значение, равное математическому ожиданию
    expected_value = 10.5 

    # задаем уровень статистической значимости
    alpha = 0.05

    # проводим двусторонний стат-тест равенства среднего выборки значению мат ожидания
    results = st.ttest_1samp(
        hero_rolls, 
        expected_value)

    # выводим статистику и результаты
    print('Разница между средним значением бросков персонажа и мат ожиданием =', round((hero_rolls.mean() - expected_value),2))
    print()
    print('p-value =', results.pvalue)
    print()
    
    if results.pvalue <  alpha and hero_rolls.mean() - expected_value > 0:
        print("Этот персонаж крайне удачлив.")
    elif results.pvalue <  alpha and hero_rolls.mean() - expected_value < 0:
        print("Этот персонаж крайне неудачлив.")
    else:
        print("Удача персонажа в рамках математической нормы.")

Как все прекрасно знают (нет), p‑value — это вероятность получить наблюдаемое значение, при условии, что нулевая гипотеза верна. Под нулевой гипотезой (H0) сверху в окошке с кодом канонично заложено именно равенство мат ожидания 10.5 и среднего значения выборки бросков для каждого персонажа. Поскольку мы проверяем двустороннюю гипотезу, то тест укажет нам на особо удачливых/неудачливых персонажей при значении p‑value меньше 0.025.

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

Ни для одного персонажа p‑value не достигло заветного значения 0.025. И это даже без поправки в уровень статистической значимости из‑за множественной проверки гипотез. Поправка уменьшила бы параметр alpha, принятой нам по классике за 5%, и сделала бы тест строже. Наименьший p‑value в 27% был получен при проверке бросков персонажа «Соня». Совершив 245 бросков кубика d20 со средним в 10.92, она должна получить статус самой удачливой героини Кампании. Но не аномально удачливой с точки зрения математики.

Пришло время, склонив голову, перейти к выводам.


Акт III: Выводы

Гипотеза, которая в рамках повествования превратилась в "среднее значение бросков кубика d20 за все партии статистически значимо отличается от матожидания 10.5 для каждого из героев" была проверена и отвергнута. Ни для одного из персонажей стат-тест не показал значимого отличия от математического ожидания.

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


Акт IV: Секретная концовка: Удача 2.0

Вы еще здесь? Прекрасно. У меня осталось еще пару мыслей по поводу удачи.

Один вопрос не давал мне покоя во время подготовки статьи. Я оценивал удачу исключительно математически. Возможно ли, что я делал это слишком «сухо»? Можем ли мы сделав 10, 20, 50 бросков за игру ПОЧУВСТОВАТЬ, что нам везет, если среднее значение наших бросков отклоняется от матожидания на пару десятых. Скорее нет, ответил я себе. Это ощущение затеряется.

И тут я решил, что для оценки удачи в DnD нужно создать новую метрику! Удача 2.0!

Ранее я определял удачу исключительно по уровню 10.5 матожидания и ряда ста‑тестов. Я предположил, что заметил бы, что сегодня 20 гранный кубик мне особенно благоволит, если бы видел на выпадающих гранях кубика 2 цифры, а не одну в два раза чаще! Представьте себе, что разбивая целый десяток яиц для завтрака, вы находите двойной желток как минимум в 7 из них!

Удача 2.0 наглядно: в рамках одной игры вам выпало в два раза больше двузначных значений.
Удача 2.0 наглядно: в рамках одной игры вам выпало в два раза больше двузначных значений.

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

Поэтому я сделал новые расчеты, не надеясь, что хотя бы в одной из 14-ти наших партий найдется персонаж, для которого это условие будет выполнено в какую‑либо из сторон. В сторону очень сильной удачи или наоборот. И каково же было мое удивление, когда такие партии нашлись и не одна‑две за все время, а минимум по 5 штук на каждого из нас!

Ни у одного персонажа по новой метрике количество неудачных партий не превышает количество удачных. Это ли не удача?
Ни у одного персонажа по новой метрике количество неудачных партий не превышает количество удачных. Это ли не удача?


Оказалось, что по метрике Удача 2.0, которую я сам изобрел, самым удачливым оказался именно мой персонаж. Да, бард Скрип Сосны - это персонаж автора этой статьи. Задумывалась ли метрика именно для такого исхода? Нееееет, ни в коем случае. Доволен ли я таким исходом? Несомненно.

Скрип благодарит тебя, приключенец - читатель,  за твое время. Пускай твой день будет удачным!
Скрип благодарит тебя, приключенец — читатель, за твое время. Пускай твой день будет удачным!

Комментарии (0)