老虎機

老虎機數學模型揭密:我自己做了一台 32 格轉輪機,算給你看 RTP 怎麼來

我是工程師,看不懂一樣東西就會想自己做一台。老虎機的「數學模型」聽起來很高深,但我真的坐下來用 32 格轉輪做了一台最小可行的機台,手算期望值,再寫程式轉 500 萬次驗證。這篇就是我做的過程,順便把 RTP、命中率、波動率三個名詞一次講清楚。

TL;DR

  • RTP 不是測出來的,是算出來的:每個組合的機率 × 賠付,全部加起來。我的 32 格機台手算 93.01%,模擬 500 萬次得到 92.96%。
  • 動一格就天差地遠:把每個轉輪的 7 從 1 格改成 2 格,RTP 從 93% 跳到 114%(廠商賠錢),所以設計師是用「格數」在調 RTP。
  • 玩家看不到轉輪表,但 1,000 轉的實際回收可以從 72% 到 118%,短期數字根本不能拿來推 RTP。

老虎機的三張表:轉輪表、賠付表、權重

一台老虎機的數學核心就三樣東西:

  1. 轉輪表(reel strip):每個轉輪上有幾格、每格放什麼符號。你在螢幕上看到的轉輪動畫只是表演,真正決定結果的是這張表。
  2. 賠付表(paytable):哪些組合賠多少倍。這張表遊戲裡通常找得到。
  3. 亂數:RNG 替每個轉輪挑一個停格位置。這部分我在老虎機 RNG 怎麼運作那篇寫過。

Wikipedia 的老虎機條目有提到,最早的機械機台每個轉輪 10 個符號,3 個轉輪只有 1,000 種組合,頭獎最多就是千分之一。後來的電子機台用「虛擬轉輪」讓一個實體符號對應多個虛擬格,才做得出百萬分之一的頭獎。線上老虎機更簡單,轉輪表就是程式裡的一個陣列。

我做的機台:3 轉輪 × 32 格

我設計的假想機台長這樣,三個轉輪一樣:

符號 每個轉輪的格數 單格機率
7 1 1/32
BAR 4 4/32
櫻桃 7 7/32
空格 20 20/32

賠付表(只有一條線):

組合 賠付(倍注)
7-7-7 1,000
BAR-BAR-BAR 60
櫻桃-櫻桃-櫻桃 25
第一輪櫻桃(不論後面) 2.5

總組合數是 32 × 32 × 32 = 32,768。接下來就是把每種中獎組合的機率乘賠付,加起來。

手算 RTP:每一條都要能回溯

組合 組合數 機率 賠付 貢獻 RTP
7-7-7 1 1/32,768 1,000 3.05%
BAR × 3 4³ = 64 1/512 60 11.72%
櫻桃 × 3 7³ = 343 約 1/96 25 26.17%
第一輪櫻桃(排除三櫻桃) 6,825 約 1/5 2.5 52.07%
合計 命中率 22.07% 93.01%

這張表就是這台機的「數學模型」。幾個觀察:

  • 超過一半的 RTP 來自每 5 轉中一次的 2.5 倍小獎。這就是為什麼你玩的時候「一直有中」卻一直在賠:命中率高 ≠ 賠得多。
  • 頭獎 1,000 倍只佔 3% 的 RTP,但它是廣告上最大的數字。
  • 標準差算出來是 6.67 倍注,這個數字就是波動率。

我一開始用了另一套賠付(頭獎 500 倍、BAR 50、櫻桃 15),手算出來 RTP 只有 51.7%,自己嚇一跳,想說是不是程式寫錯。檢查三次才確認沒錯,是我的賠付表太小氣。這才體會到設計師的工作就是在這張表上反覆微調,直到 RTP 落在 92%~97% 之間。

用程式驗證:500 萬轉

手算完當然要驗。我寫了十幾行 Python,把三個轉輪各丟一個 0~31 的亂數,查表賠付,轉 500 萬次:

import random
reel = ['7'] + ['BAR']*4 + ['CH']*7 + ['BL']*20   # 32 格
pays = {('7','7','7'):1000, ('BAR','BAR','BAR'):60, ('CH','CH','CH'):25}
def spin():
    a, b, c = (random.choice(reel) for _ in range(3))
    pay = pays.get((a, b, c), 0)
    return pay if pay else (2.5 if a == 'CH' else 0)
N = 5_000_000
print(sum(spin() for _ in range(N)) / N)   # 我跑出 0.9296

跑出 92.96%,跟手算的 93.01% 差 0.05 個百分點,這是 500 萬次抽樣的正常誤差。這就是大數法則在做事:樣本夠大,平均值就會貼近理論值。

但如果樣本不夠大呢?我把同一台機切成一段段 1,000 轉來看:

樣本大小 第 5 百分位 中位數 第 95 百分位
1,000 轉 72.0% 89.8% 118.0%
100,000 轉 89.9% — 96.75%

1,000 轉的實際回收從 72% 到 118% 都很正常。 一個玩家一個晚上大概就是幾百到一千轉,所以任何人說「我玩了一晚算出這台 RTP」都是在算雜訊。

設計師怎麼調 RTP:動一格就是好幾個百分點

同一台機,我試了三個改法:

改動 RTP 命中率
原版 93.01% 22.07%
每輪 7 從 1 格改 2 格 114.37% 22.09%
每輪櫻桃從 7 格改 8 格 112.43% 25.20%
7-7-7 賠付從 1,000 改 2,000 96.06% 22.07%(標準差從 6.67 升到 11.66)

前兩個改法會讓廠商賠錢,所以不會有人這樣做;但它說明一件事:RTP 對轉輪格數極度敏感。把頭獎賠付加倍只讓 RTP 多 3 個百分點,卻讓標準差(波動率)幾乎翻倍。這就是「同樣 96% RTP 卻有高低波動」的來源,詳見波動率怎麼判讀。

真實遊戲比我的玩具複雜很多:5 個轉輪、每輪 50~100 格、數十條線或 Megaways、Scatter、Wild、免費旋轉、乘數。但原理一模一樣,就是一張更大的表。NetEnt 的 Starburst 官方頁寫 RTP 96.08%、命中率 23%、最大 800 倍;Pragmatic Play 的 Gates of Olympus 寫 96.50%。那些數字都是設計師在轉輪表上調出來的,不是測出來的。

從我的玩具放大到真實遊戲

我的機台 3 個轉輪、32 格,全部組合只有 32,768 種,用紙筆就能算完。真實遊戲通常是 5 個轉輪、每輪 50~100 格,組合數是 100 的 5 次方 = 100 億種;再加上多條線、Scatter 觸發的免費旋轉、乘數、消除連鎖,完整枚舉會很慢,所以設計師會混用兩種方法:能枚舉的部分精算(一般旋轉的連線賠付),枚舉不完的部分用大量模擬逼近(免費旋轉這種有分支的流程),再把兩部分加起來。

這也是為什麼第三方認證實驗室驗 RTP 的方式是「拿到轉輪表跟程式碼,自己重算一次,再跑上億次模擬確認」。他們驗的是數學模型本身,不是坐在機台前面轉幾萬次。

另一個真實遊戲常見的做法是權重轉輪:同一個符號在轉輪表上可以有不同權重,程式不是均勻抽格子,而是照權重抽。效果跟「多放幾格」一樣,只是更方便微調。對玩家來說兩者沒有差別,RTP 都是算出來的常數。

玩家能從數學模型學到什麼

你拿不到轉輪表,但有幾件事是確定的:

  • RTP 是常數。 它不會因為「剛吐過大獎」「這台很冷」而改變。每一轉都是同一張表、同一組機率。
  • 公開的 RTP 只能相信官方。 遊戲規則頁或廠商官網的數字是由數學模型算出來、經過第三方實驗室驗證的;論壇上「實測 RTP」全是小樣本雜訊。
  • 命中率跟 RTP 要分開看。 一台命中率 45% 的機可能大半是賠 0.5 倍的「中獎」,詳見命中率解析。
  • 波動率看最大獎佔多少 RTP。 最大獎賠付越高、機率越低,波動越大,你的錢消失得越不均勻。

常見問題

老虎機的 RTP 是誰決定的? 遊戲數學設計師。他們排好每個轉輪上的符號數量(轉輪表)和賠付表,把所有組合的機率乘上賠付加總,就是 RTP。RTP 是設計出來的常數,不會因為時間、地點或你怎麼按而改變。

轉輪上看起來很多 7,為什麼很少連線? 畫面上看到的轉輪只是動畫,真正決定結果的是程式裡的轉輪表。一格 7 在 32 格裡出現機率是 1/32,三個轉輪同時出 7 是 1/32,768。

命中率高的機台是不是比較好? 不一定。我的模型裡 52% 的 RTP 來自每 5 轉就中一次的 2.5 倍小獎,命中率 22% 但大部分是小賠。命中率只告訴你多常中,不告訴你中多少。

自己玩幾千轉可以算出一台機的 RTP 嗎? 不行。我的模型 1,000 轉的實際回收在 72% 到 118% 之間都很常見,要到 10 萬轉才縮到 90%~97%。玩家能看到的樣本永遠太小。

延伸閱讀