Игра в кости лжеца - отличная. Легко выучить, сложно освоить. Удачный баланс удачи и стратегии. Если вы не знаете игру, я рекомендую вам проверить ее, она отлично подходит для группы.
В нашей последней сессии мы столкнулись с интересной ситуацией, когда дошли до последних двух. У одного игрока были все 6 оставшихся кубиков, в то время как у его соперника остался один. Конечно, это вызвало много дискуссий и побочных ставок. В основном мы задались целью (читай: аргументировано), чтобы ответить на следующие вопросы:
Может ли игрок со всеми шестью кубиками разработать оптимальную стратегию, гарантирующую победу?
Если нет, каковы шансы игрока, у которого есть только один кубик?
И вот так родилась ставка. Ставка, даже не вовлекающая двух игроков, фактически играющих в игру.
Стратегия
Прежде чем мы перейдем к ставке, нам нужно было согласовать стратегию игрока со всеми 6 кубиками. Мы довольно быстро пришли к выводу, что во избежание «блефа» игроку с 6 следует просто коллировать самую высокую цену, которую он может уравнять, и надеяться, что оппонент с 1 кубиком не сможет его победить. Итак, учитывая кубик 1, 1, 3, 4, 4, 5
, он должен назвать четыре 4
(1
s - дикие).
Игроки
После прохождения минимальных курсов теории игр в колледже я склонен предполагать, что всегда есть какая-то странная оптимальная стратегия. Мне не удалось найти указанную стратегию, но я, конечно, сразу же начал пробовать. Моя цель состояла в том, чтобы найти некоторую последовательную стратегию (такую, которая не допускала бы переменного блефа, несмотря на то, что это ключевой компонент игры), а затем рассчитать шансы того, как часто она будет выигрывать. Статистический (а значит, верный, верно?) Подход к проблеме.
По другую сторону пари был мой друг Курт. Курт, давно играющий в карты, не сразу задумывается о математике. Вместо этого он быстро начинает прокручивать в своей голове тысячи итераций того, как могла бы развиваться игра. Его интуиция относительно шансов и возможность наблюдать за игрой столько раз позволяет ему определять, как часто каждый игрок будет выигрывать.
Ставка
Моя быстрая математика показала мне, что игрок со всеми 6 кубиками проиграет только в том случае, если у оппонента будет тот же номер, который он назвал, или если у него будет 1
(подстановочная карта). Учитывая 1, 1, 3, 4, 4, 5
и колл четырех 4
, проигравший выигрывает только тогда, когда у него есть 4
или 1
, что позволяет ему коллировать пять 4
и выиграть. Выпадение 1
и другой конкретный бросок будут происходить 1 из 3 раз, и это должно произойти 6 раз подряд, чтобы проиграть. Другими словами, только 1 из 729 раз выиграет проигравший.
Курт проделал в своей голове какой-то другой вид магии вуду игрока и смело воскликнул: «Если вы дадите мне 1 кубик против ваших 6 15 раз подряд, держу пари, я выиграю один». Я только что рассчитал шансы со 100% уверенностью (а может, и нет ...) увидел возможность нанести удар. Я так быстро ответила: «Ты в курсе», что Курт предположил, что он сомневается, основываясь на моей уверенности. Я немного отказался от его просьбы о коэффициенте 2: 1 (он уже получил коэффициенты, прогнав его 15 раз), но в конце концов сдался, думая, что я все еще статистический блокировщик.
6 кубиков против 1 кубика. 15 раз подряд.
Время играть.
Результат
Первые несколько поворотов прошли точно по плану. Я бы назвал что-то вроде трех 5
, у Курта 3
, игра окончена.
По большей части первые 10 игр прошли отлично. Курт бросил там пару 1
, но каждый раз на следующем ходу он проигрывает. Но потом, где-то около 10-й игры, что-то произошло.
Я выбросил 1 1 3 4 4 5
и, в соответствии со стратегией, колл четыре 4
, максимум, который я мог безопасно коллировать. Затем Курт возвращается с четырьмя 5
, бросив свой собственный 5
.
Вот дерьмо.
Я проиграл, а он не выполнил ни дубликата, ни 1
. В конце концов я все равно выиграл ту игру, но он все же поставил у меня до трех кубиков. Я прошел следующие несколько игр без проблем и выиграл пари. Но мой интерес был возбужден. Мои предположения и, следовательно, мои шансы были неверными. Я должен узнать, что они на самом деле.
Моделирование
Теперь, понимая, что проблема, возможно, сложнее, чем может решить простая статистика, я решил написать простой сценарий моделирования, который мог бы запускать множество попыток, чтобы получить оценку шансов. Это также казалось хорошей возможностью протестировать Jupyter Notebooks, что я давно собирался сделать. Весь код и записные книжки iPython для этого проекта доступны на GitHub.
Построить рандомизацию игральных костей, общий игровой процесс и мою простую стратегию, основанную на правилах, не блефовать, было не так уж сложно. Реальной переменной в этой ситуации является стратегия, которую должен использовать Курт.
Заезд 1 - Первый верх
В качестве проверки вменяемости я хотел проверить свои первоначальные шансы и дать Курту базовую стратегию. Что бы я ни предлагал, Курт делает еще одну ставку и надеется, что у него есть 1
или какой бы номер я ни назвал. Не умно, но хорошая отправная точка.
def get_kurts_bid(my_dice, num_dice_matt_has, matts_bid=None):
if matts_bid is None:
# If Matt has not bid yet start off with 1 of my dice
return (1, my_dice)
else:
# Return one more of what Matt said
return (matts_bid[0] + 1, matts_bid[1])
Полученные результаты:
Simulation Complete
-------------------
Num Simulations: 10,000,000
Took: 247.9 seconds
Kurt Wins: 13,742
Win Percent: 0.14%
Wins 1 in 727.70 times
Конечно, 10 миллионов симуляций показывают, что мои шансы 1 к 729 были правильными. Это также, что, возможно, более важно, показывает, что код работает. Пора начинать оптимизацию.
Заезд 2 - Хороший догадыватель
Может быть, мы сможем добиться большего, если попытаемся заманить Мэтта в ловушку на первоначальной ставке. Вместо того, чтобы позволить Мэтту вести дело, Курт может попытаться угадать номер, по которому Мэтт все равно позвонил бы. Первоначальное предположение о трех любых кубиках, которые бросает Курт, кажется хорошим предположением.
def get_kurts_bid(my_dice, num_dice_matt_has, matts_bid=None): if my_dice == 1: if matts_bid is None: return (1, 2) else: return (matts_bid[0] + 1, matts_bid[1])
else: if matts_bid is None: return (3, my_dice) else: return (matts_bid[0] + 1, matts_bid[1])
Полученные результаты:
Simulation Complete
-------------------
Num Simulations: 10,000,000
Took: 243.0 seconds
Kurt Wins: 14,365
Win Percent: 0.14%
Wins 1 in 696.14 times
Незначительное улучшение, упало до 1 из 696 раз, когда Курт выигрывал. Это действительно имеет смысл, в основном из-за игрового процесса. Как только Курт выигрывает первый ход, Мэтт становится первым в последующих ходах. Так что на самом деле эта стратегия влияет только на самый первый ход игры.
Run 3 - The End Gamer
Поскольку предыдущая стратегия повлияла только на первый ход, давайте посмотрим, сможем ли мы стать умнее к концу игры, если у нас получится.
Когда дело доходит до Мэтта, имеющего два или меньше кубиков, Курт хочет угадать два из его кубиков. Надежда - Мэтт бросает 1, 3
, а Курт 4
. Мэтт угадывает два 3
, Курт возвращается с двумя 4
и выигрывает.
def get_kurts_bid(my_dice, num_dice_matt_has, matts_bid=None): # When Matt has 2 or less dice, guess 2 of whatever I have if I can, otherwise guess 3 of them if num_dice_matt_has <= 2: if (2, my_dice) > matts_bid: return (2, my_dice) return (3, my_dice) if my_dice == 1: if matts_bid is None: return (1, 2) else: return (matts_bid[0] + 1, matts_bid[1])
else: if matts_bid is None: return (3, my_dice) else: return (matts_bid[0] + 1, matts_bid[1])
Полученные результаты:
Simulation Complete
-------------------
Num Simulations: 10,000,000
Took: 243.5 seconds
Kurt Wins: 14,831
Win Percent: 0.15%
Wins 1 in 674.26 times
Немного лучше, но мы по-прежнему не причиняем такого большого ущерба. В любом случае Курт доходит до двух последних кубиков примерно 1 из 80 раз. Любая стратегия, которую мы здесь реализуем, не слишком помогает в целом.
Заезд 4 - Скрещивание пальцев
Давайте применим ситуацию, которая произошла в реальной игре. В качестве напоминания Мэтт выбросил 1 1 3 4 4 5
и назвал четыре 4
. Затем Курт вернулся с четырьмя 5
, скатав свой собственный 5
. Таким образом, стратегия Курта состоит в том, чтобы угадать то же количество, которое предлагает Мэтт, но вместо того, которое у него есть. Есть надежда, что у Мэтта есть только один естественный бросок из этого числа, а остальные 1
s.
def get_kurts_bid(my_dice, num_dice_matt_has, matts_bid=None): # When Matt has 2 or less dice, guess 2 of whatever I have if I can, otherwise guess 3 of them if num_dice_matt_has <= 2: if (2, my_dice) > matts_bid: return (2, my_dice) return (3, my_dice) if my_dice == 1: if matts_bid is None: return (1, 2) else: return (matts_bid[0] + 1, matts_bid[1])
else: if matts_bid is None: return (3, my_dice) # Might as well try and trap him elif (matts_bid[0], my_dice) > matts_bid: return (matts_bid[0], my_dice) # Hoping for [1, 1, 3] against [4] else: return (matts_bid[0] + 1, my_dice) # Hope he has all 1s?
Полученные результаты:
Simulation Complete
-------------------
Num Simulations: 10,000,000
Took: 294.1 seconds
Kurt Wins: 89,389
Win Percent: 0.89%
Wins 1 in 111.87 times
Оооо, прогресс. Курт сейчас выигрывает 1 из 112 раз. Эта ситуация, когда есть все 1
и один натуральный, на самом деле случается часто, особенно ближе к концу игры, когда остается меньше кубиков.
В последнем случае, если Мэтт вызывает три 4
, а у меня, например, 3
, Курт вызовет четыре 3
. Насколько я могу судить, это происходит только тогда, когда Мэтт выбрасывает все 1
, так что, вероятно, не много.
Прогон 5 - Настройщик
Поразмыслив над последней стратегией, я понимаю, что она, по сути, такая же, как и исходная конечная стратегия. На самом деле, это даже лучшая стратегия в конце игры! Предыдущая стратегия конечной игры, предполагающая угадать 2 из того, что есть у Курта (если возможно), не учитывает бросок Мэтта на 45 и Курта на 46. Мэтт угадывает одну 4, Курт должен угадать одну 5, но раньше угадывал две 5
.
Давайте применим общую стратегию игры и к финальной игре.
def get_kurts_bid(my_dice, num_dice_matt_has, matts_bid=None): if my_dice == 1: if matts_bid is None: return (1, 2) else: return (matts_bid[0] + 1, matts_bid[1])
else: if matts_bid is None: return (3, my_dice) # Might as well try and trap him elif (matts_bid[0], my_dice) > matts_bid: return (matts_bid[0], my_dice) # Hoping for [1, 1, 3] against [4] else: return (matts_bid[0] + 1, my_dice) # Hope he has all 1s
Полученные результаты:
Simulation Complete
-------------------
Num Simulations: 10,000,000
Took: 301.5 seconds
Kurt Wins: 354,633
Win Percent: 3.55%
Wins 1 in 28.20 times
Ухааа !! Курт выигрывает таким образом 1 из 28 раз!
Возможно, это имеет смысл. Курту просто нужно сделать пару поворотов, свернув 1
или такой же, как у меня, а затем он должен рассчитывать на то, что я брошу 1
. Это определенно случается, и оказывается, что это случается примерно в 3,5% случаев.
Исход
Итак, 15 попыток с коэффициентом 2: 1 на самом деле сейчас выглядят неплохо.
Что еще более важно, это показывает, что интуиция Курта была почти правильной. Это действительно увлекательно для меня, просто опираясь на прошлый опыт и видя столько бросков кубиков, Курт смог почти точно предсказать шансы этого сложного сценария.
По крайней мере, я все же выиграл пари.
Это сообщение размещено в личном блоге Мэтта Доджа. Прочтите исходный пост здесь.