Какова оптимальная стратегия выигрыша для этой модифицированной игры в блэкджек?

Вопросы

Есть ли лучшая цена, чтобы я мог выиграть как можно больший процент игр? Если так, то, что это?

Изменить: Существует ли точная вероятность выигрыша, которая может быть рассчитана для данного лимита, независимо от того, что делает противник? (Я не делал вероятности и статистику с колледжа). Мне было бы интересно увидеть это как ответ, чтобы сопоставить его с моими смоделированными результатами.

Редактировать: Исправлены ошибки в моем алгоритме, обновлена ​​таблица результатов.

Фон

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

Модифицированные правила блэкджека

  1. Ровно два человека (дилер не имеет значения)
  2. Каждому игроку сдаются две карты лицом вниз
    • Ни один из игроков _ever_ не знает значения _any_ карт противника
    • Ни один из игроков не знает значения руки противника, пока _both_ не закончит раздачу
  3. Цель - приблизиться к 21 очку. Результаты:
    • Если у игрока A & B одинаковый счет, игра является ничьей
    • Если оба игрока A & B набрали более 21 балла, игра считается ничьей
    • Если счет игрока А равен <= 21, а игрок Б выиграл, игрок А выигрывает
    • Если счет игрока А больше, чем у игрока Б, и ни один из них не выиграл, игрок А выигрывает
    • В противном случае игрок A проиграл (B выиграл).
  4. Карты стоят:
    • Карты со 2 по 10 приносят соответствующее количество очков
    • Карты J, Q, K стоят 10 очков.
    • Карта туза стоит 1 или 11 очков
  5. Каждый игрок может запросить дополнительные карты по одной до тех пор, пока:
    • Игрок больше не хочет (остаться)
    • Оценка игрока, с любым тузом, подсчитанным как 1, превышает 21 (бюст)
    • Ни один из игроков не знает, сколько карт использовал другой.
  6. После того, как оба игрока останутся или будут разыграны, победитель определяется согласно правилу 3 выше.
  7. После каждой раздачи вся колода перетасовывается, и все 52 карты снова в игре.

Что такое колода карт?

Колода карт состоит из 52 карт по четыре из следующих 13 значений:

2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A

Никакое другое свойство карт не имеет отношения к делу.

Представление Ruby об этом:

CARDS = ((2..11).to_a+[10]*3)*4

Алгоритм

Я подхожу к этому следующим образом:

  • Я всегда буду хотеть ударить, если мой счет от 2 до 11, так как невозможно разорить
  • Для каждой из оценок от 12 до 21 я буду моделировать N рук против оппонента.
    • Для этих N рук счет будет моим "пределом". Как только я достигну предела или больше, я останусь.
    • Мой противник будет следовать той же стратегии
    • Я буду моделировать N рук для каждой перестановки множеств (12..21), (12..21)
  • Выведите разницу в выигрышах и проигрышах для каждой перестановки, а также разницу в чистых выигрышах

Вот алгоритм, реализованный в Ruby:

#!/usr/bin/env ruby
class Array
  def shuffle
    sort_by { rand }
  end

  def shuffle!
    self.replace shuffle
  end

  def score
    sort.each_with_index.inject(0){|s,(c,i)|
      s+c > 21 - (size - (i + 1)) && c==11 ? s+1 : s+c
    }
  end
end

N=(ARGV[0]||100_000).to_i
NDECKS = (ARGV[1]||1).to_i

CARDS = ((2..11).to_a+[10]*3)*4*NDECKS
CARDS.shuffle

my_limits = (12..21).to_a
opp_limits = my_limits.dup

puts " " * 55 + "opponent_limit"
printf "my_limit |"
opp_limits.each do |result|
  printf "%10s", result.to_s
end
printf "%10s", "net"
puts

printf "-" * 8 + " |"
print "  " + "-" * 8
opp_limits.each do |result|
  print "  " + "-" * 8
end
puts

win_totals = Array.new(10)
win_totals.map! { Array.new(10) }

my_limits.each do |my_limit|
  printf "%8s |", my_limit
  $stdout.flush
  opp_limits.each do |opp_limit|

    if my_limit == opp_limit # will be a tie, skip
      win_totals[my_limit-12][opp_limit-12] = 0
      print "        --"
      $stdout.flush
      next
    elsif win_totals[my_limit-12][opp_limit-12] # if previously calculated, print
      printf "%10d", win_totals[my_limit-12][opp_limit-12]
      $stdout.flush
      next
    end

    win = 0
    lose = 0
    draw = 0

    N.times {
      cards = CARDS.dup.shuffle
      my_hand = [cards.pop, cards.pop]
      opp_hand = [cards.pop, cards.pop]

      # hit until I hit limit
      while my_hand.score < my_limit
        my_hand << cards.pop
      end

      # hit until opponent hits limit
      while opp_hand.score < opp_limit
        opp_hand << cards.pop
      end

      my_score = my_hand.score
      opp_score = opp_hand.score
      my_score = 0 if my_score > 21 
      opp_score = 0 if opp_score > 21

      if my_hand.score == opp_hand.score
        draw += 1
      elsif my_score > opp_score
        win += 1
      else
        lose += 1
      end
    }

    win_totals[my_limit-12][opp_limit-12] = win-lose
    win_totals[opp_limit-12][my_limit-12] = lose-win # shortcut for the inverse

    printf "%10d", win-lose
    $stdout.flush
  end
  printf "%10d", win_totals[my_limit-12].inject(:+)
  puts
end

использование

ruby blackjack.rb [num_iterations] [num_decks]

По умолчанию в скрипте 100000 итераций и 4 колоды. 100000 занимает около 5 минут на быстром MacBook Pro.

Выход (N = 100 000)

                                                       opponent_limit
my_limit |        12        13        14        15        16        17        18        19        20        21       net
-------- |  --------  --------  --------  --------  --------  --------  --------  --------  --------  --------  --------
      12 |        --     -7666    -13315    -15799    -15586    -10445     -2299     12176     30365     65631     43062
      13 |      7666        --     -6962    -11015    -11350     -8925      -975     10111     27924     60037     66511
      14 |     13315      6962        --     -6505     -9210     -7364     -2541      8862     23909     54596     82024
      15 |     15799     11015      6505        --     -5666     -6849     -4281      4899     17798     45773     84993
      16 |     15586     11350      9210      5666        --     -6149     -5207       546     11294     35196     77492
      17 |     10445      8925      7364      6849      6149        --     -7790     -5317      2576     23443     52644
      18 |      2299       975      2541      4281      5207      7790        --    -11848     -7123      8238     12360
      19 |    -12176    -10111     -8862     -4899      -546      5317     11848        --    -18848     -8413    -46690
      20 |    -30365    -27924    -23909    -17798    -11294     -2576      7123     18848        --    -28631   -116526
      21 |    -65631    -60037    -54596    -45773    -35196    -23443     -8238      8413     28631        --   -255870

интерпретация

Вот где я борюсь. Я не совсем уверен, как интерпретировать эти данные. На первый взгляд кажется, что всегда оставаться в 16 или 17 - это путь, но я не уверен, так ли это легко. Я думаю, что маловероятно, что реальный человеческий оппонент останется на 12, 13 и, возможно, 14, так что я должен выбросить эти значения противник-предел? Кроме того, как я могу изменить это, чтобы учесть изменчивость реального человеческого оппонента? например, реальный человек, скорее всего, останется на 15 только из-за "чувства" и может также попасть в 18 из-за "чувства"

3 ответа

Решение

Я с подозрением отношусь к вашим результатам. Например, если противник стремится к 19, ваши данные говорят о том, что лучший способ победить его - это наносить удары, пока вы не достигнете 20. Это не проходит базовый тест на запах. Вы уверены, что у вас нет ошибки? Если мой оппонент стремится к 19 или выше, моя стратегия состоит в том, чтобы избежать разорения любой ценой: остаться на что-нибудь 13 или выше (может быть, даже 12?). Идти за 20 - неправильно, и не только с небольшим отрывом, но и с большим.

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

Когда я делаю следующие замены для вашего кода:

# Replace scoring method.
def score
  s = inject(0) { |sum, c| sum + c }
  return s if s < 21
  n_aces = find_all { |c| c == 11 }.size
  while s > 21 and n_aces > 0
      s -= 10
      n_aces -= 1
  end
  return s
end

# Replace section of code determining hand outcome.
my_score  = my_hand.score
opp_score = opp_hand.score
my_score  = 0 if my_score  > 21
opp_score = 0 if opp_score > 21
if my_score == opp_score
  draw += 1
elsif my_score > opp_score
  win += 1
else
  lose += 1
end

Результаты согласуются с поведением дилеров казино: 17 является оптимальной целью.

n=10000
                                                       opponent_limit
my_limit |        12        13        14        15        16        17        18        19        20        21       net
-------- |  --------  --------  --------  --------  --------  --------  --------  --------  --------  --------  --------
      12 |        --      -843     -1271     -1380     -1503     -1148      -137      1234      3113      6572
      13 |       843        --      -642     -1041     -1141      -770       -93      1137      2933      6324
      14 |      1271       642        --      -498      -784      -662        93      1097      2977      5945
      15 |      1380      1041       498        --      -454      -242      -100       898      2573      5424
      16 |      1503      1141       784       454        --      -174        69       928      2146      4895
      17 |      1148       770       662       242       174        --        38       631      1920      4404
      18 |       137        93       -93       100       -69       -38        --       489      1344      3650
      19 |     -1234     -1137     -1097      -898      -928      -631      -489        --       735      2560
      20 |     -3113     -2933     -2977     -2573     -2146     -1920     -1344      -735        --      1443
      21 |     -6572     -6324     -5945     -5424     -4895     -4404     -3650     -2560     -1443        --

Несколько разных комментариев:

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

Два комментария:

  1. Похоже, что не существует единой доминирующей стратегии, основанной на "пределе попаданий":

    • Если вы выберете 16, ваш противник может выбрать 17
    • если вы выберете 17, ваш противник может выбрать 18
    • если вы выберете 18, ваш противник может выбрать 19
    • если вы выберете 19, ваш противник может выбрать 20
    • если вы выберете 20, ваш противник может выбрать 12
    • если вы выберете 12, ваш противник может выбрать 16.

2. Вы не упоминаете, могут ли игроки видеть, сколько карт вытянул их противник (я бы так предположил). Я ожидаю, что эта информация будет включена в "лучшую" стратегию. (Ответил)


Без информации о решениях других игроков игра становится проще. Но поскольку явно не существует доминирующей "чистой" стратегии, оптимальной стратегией будет " смешанная " стратегия. То есть: набор вероятностей для каждой оценки от 12 до 21 для того, стоит ли вам останавливать или брать другую карту (РЕДАКТИРОВАТЬ: вам понадобятся разные вероятности для данной оценки без тузов по сравнению со счетом с тузами.) Выполнение стратегии требует Вы случайным образом выбираете (в соответствии с вероятностями), останавливаться или продолжать после каждого нового розыгрыша. Затем вы можете найти равновесие Нэша для игры.

Конечно, если вы задаете только более простой вопрос: какова оптимальная стратегия выигрыша против неоптимальных игроков (например, тех, которые всегда останавливаются на 16, 17, 18 или 19), вы задаете совершенно другой вопрос, и вам придется точно укажите, каким образом другой игрок ограничен по сравнению с вами.

Вот несколько соображений о данных, которые вы собрали:

  • Это мягко полезно для определения того, каким должен быть ваш "предел попадания", но только если вы знаете, что ваш оппонент придерживается аналогичной стратегии "ограничения попадания".
  • Даже тогда, это действительно очень полезно, если вы знаете, каков или может быть "предел" попадания вашего оппонента. Вы можете просто выбрать лимит, который даст вам больше побед, чем они.
  • Вы можете более или менее игнорировать фактические значения в таблице. Важен ли он положительным или отрицательным.

Чтобы показать ваши данные иначе, первое число - это предел вашего оппонента, а вторая группа чисел - это пределы, которые вы можете выбрать и выиграть. "Звездочка" - самый выигрышный выбор:

12:   13, 14, 15, 16*, 17, 18
13:   14, 15, 16*, 17, 18, 19
14:   15, 16, 17*, 18, 19
15:   16, 17*, 18, 19
16:   17, 18*, 19
17:   18*, 19
18:   19*, 20
19:   12, 20*
20:   12*, 13, 14, 15, 16, 17
21:   12*, 13, 14, 15, 16, 17, 18, 19, 20

Из этого вы можете видеть, что предел попадания 17 или 18 является наиболее безопасным вариантом, если противник следует случайной стратегии выбора "предела попадания", потому что 17 и 18 побьют 7/10 "пределов попадания" противника.

Конечно, если ваш оппонент человек, вы не можете ответить на него, налагая "лимит попадания" до 18 или более 19, так что это полностью сводит на нет предыдущие вычисления. Я все еще думаю, что эти цифры полезны, однако:


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

Если вы думаете, что они настроены оптимистично или они готовы рисковать, выберите лимит 20 - вы победите их в долгосрочной перспективе, если их предел превысит 17. Если вы действительно уверены в себе, выберите лимит 12 - выиграет, если их лимит превысит 18, и здесь будет гораздо более частый выигрыш.

Если вы думаете, что они консервативны или склонны к риску, выберите предел 18. Это победит, если они останутся где-то ниже 18 лет.

Для нейтральной земли, возможно, подумайте, каким будет ваш лимит без какого-либо влияния извне. Вы обычно бы попали на 16? 17?

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

Другие вопросы по тегам