《Statistically Speaking, It’s Probably a Good Game, Part 1》:遊戲設計者的基礎機率入門

La Penseur原文出處:Statistically Speaking, It’s Probably a Good Game, Part 1: Probability for Game Designers

本文作者是一位遊戲設計者,在這一系列的三篇文章中,他以生動有趣的角度介紹了「機率」「統計」兩項數學理論的基礎概念,以及兩者在遊戲中的相關應用。本篇是系列作的第一篇,解釋了機率的部分,而後的第二篇介紹統計的部分,最後一篇則是以一個 Board Game 的實例,解釋機率與統計於遊戲設計中的實際應用。我個人覺得這一系列文章非常棒,點出了很多遊戲數值設計層面的迷思與問題點,相當值得遊戲企畫者,或未來有志於從事遊戲數值企畫的讀者詳加閱讀。

許多人只要一聽到有關於「數學」的詞彙或術語,可能就會倒吸一口涼氣,然後想辦法敬而遠之。「機率」與「統計」,應該也曾經出現在大部分讀者的求學過程中,而且經常是屬於不怎麼受歡迎的兩個傢伙。但不論過去你和它們相處得好不好,和它們的關係像陌生人還是好朋友一樣,如果能夠善加利用機率與統計的知識,將能夠使許多遊戲設計的功能與機制更加完備而有趣。

文章開頭,作者就先提出了三個有趣的動腦小問題。在往下繼續閱讀之前,不妨先試著思考看看這些問題的答案:

  • 謎題一:你正在設計一個 MMO 遊戲,其中某隻怪物有 10% 的機率會在死掉之後掉落寶物。但是有位測試者告訴你,他殺了 20 隻這種怪物後,共拿到 4 次掉落的寶物;而另一位測試者,則回報在解決 20 隻怪物後,卻沒有拿到任何的掉落寶物。這是程式碼的臭蟲嗎?你應該殺去程式部門震怒拍桌子了嗎?
  • 謎題二:你要在戰鬥系統中加入「致命傷害」的要素,假設玩家的基礎攻擊命中率是 75%,只要成功擊中了對手,系統就會再做一次機率判定,如果成功通過機率運算,傷害數值就會乘以 2 倍;然後再繼續做機率判定,如果再度成功的話,傷害值就變成原來的 3 倍;以此類推下去,不斷地往上加乘。在這樣的系統設定之下,玩家的每次攻擊,至少能夠造成 2 倍傷害的機率是多少?玩家能夠造成 4 倍或 4 倍以上傷害輸出的機率是多少?
  • 謎題三:你決定在遊戲中加入一個賭博的小遊戲,讓玩家能夠下注丟擲硬幣後的正面或反面兩種結果。然而,在這個小遊戲中必須包含一個歷史紀錄,就像是賭場中的下注系統一樣,在螢幕上會顯示出最近 20 筆的遊戲結果。做為這個小遊戲的設計者,你是否應該要求程式設計者在其中加入某些特殊的運算邏輯,以防止玩家利用這些歷史紀錄的資料,贏錢贏到使你的遊戲經濟系統崩潰?

首先,在進入機率理論的基礎知識之前,先要溫故知新地喚起讀者深埋在潛意識中的記憶:「機率」「統計」的定義,究竟是什麼?

  • Probability:Predicts the chance that an event will happen.
  • Statistics:Draws conclusions based upon events that have already happened.

如上所述,所謂的機率,是能夠用來預測某事件未來可能發生的機會有多少;而所謂的統計,是用來對已發生過的事件分析出合理的結論。做為一位遊戲設計者,機率與統計所扮演的角色,應該像是在你座位抽屜中的工具箱一樣,能夠在有需要的時候立即取出來,迅速而便利地幫助你解決遊戲設計中遇到的難題。若能夠妥善地利用這些強而有力的工具,將可以使得遊戲設計的成品更加平衡也更加有趣!

談到機率,我們可能會直覺聯想到「難以預測的事物」,或「有時發生,有時不發生的東西」;實際上,由機率所反應出來的結果,是一種全然無庸置疑的事實,而非單純無依據的猜測。就像大家都知道的事實,擲出一個正常的普通六面骰子,出現點數為 6 的機率,正好是 1/6,也就是 16.7% 左右的機率。16.7%,並不是猜測臆度得來的數字,而是一個既存的事實與法則。

想要將機率理論運用到遊戲設計中的數值運算之前,必須先熟悉以下的機率事件分類:

  • 獨立事件:每一項事件的發生機率,都與任何其他事件無關。例如擲骰子一次,然後再擲第二次,兩次事件所產生的結果,完全是獨立不與其他事件相關的機率。
  • 相關事件:每一項事件的發生機率,都與其他事件相關。例如在同一副撲克牌中抽出一張牌,然後繼續再抽出第二張牌,這第二張牌所可能出現的事件機率,就會受到第一張牌結果的影響。
  • 條件機率事件:這一項事件的發生機率,需要倚靠其他事件的發生與否。例如達成致命傷害的機率,必須先仰賴攻擊命中的機率通過運算之後,才能判斷是否發生致命傷害的情況;如果攻擊命中的事件沒有成功發生,自然也就不會發生致命傷害的事件。這一項機率事件,可說是在機率運算過程中最有用的方法。

關於「機率」,一般人大多知道世界上有這樣的東西存在,但是多數人卻對於機率存在著許多的迷信以及誤解。其中最常見的錯誤認知包含:

  • 因為上次出現了點數為 5 的情況,所以認為 5 比任何其他點數出現的可能性更高。錯!
    骰子每一面的機率都是固定的 1/6 = 16.7%,而且永遠不會改變。骰子沒有記憶能力,並不會記得上次所產生的結果,更不會對未來的結果發生影響。
  • 因為之前連續 10 次沒有出現點數為 6 的結果,所以認為接下來出現點數為 6 的情況可能性將大幅增加。錯!
    同上,不論之前連續出現過幾次的點數 6,都與接下來可能出現的結果無關。因此,即使之前連續出現了 10 次點數 6 的情況,下一次的結果中出現點數為 6 的機率依舊是 1/6 不會改變。
  • 相信所謂的平均律:在經過一段很長的過程之後,所有的結果都會趨向於平衡。錯!
    是的,假設丟擲硬幣 1000 次,我們可以期望得到 50/50 的正反面結果。但是在前面 10 次丟擲中,出現 8 次正面與 2 次反面的結果,並不能保證在接下來的 10 次丟擲結果中,將會出現比較多的硬幣反面。以 100 萬次的結果來看,或許正面與反面的結果會相當趨近,但是即使只有 1% 的合理誤差,也會產生出 1 萬次的差異結果!

上述的例子,在條列式的敘述說明中,似乎顯得非常清楚而無須存疑。你可能會懷疑:「沒有人會犯這種顯而易見的錯誤!」然而,如果類似情形發生在賭博遊戲中,可能就會有些不同了:

在莊家與玩家對峙的擲骰子賭局中,莊家已經擲出了 2 個點數 5 的結果。

玩家:「連續出現三個 5 的可能性是 1/6 x 1/6 x 1/6 = 1/216,小於 0.5% 的機率,所以接下來擲出的結果絕對不可能是 5!」於是把籌碼下注在點數 5 以外的地方。

莊家:「事實上,下一次擲出 5 的機率依舊是 1/6 = 16.7%。」

上述的情境,也就是所謂的「賭徒誤謬」(Gambler’s Fallacy) 情境。賭徒誤謬理論是一種錯誤的想法,誤認為在隨機序列中,後續所發生的事件機率,會受到先前的事件結果所影響。而這也就是前述莊家與玩家擲骰子的情境狀況。

在計算機率問題時,一個很重要的概念與方法就是利用所謂的反向機率 (Converse Probability)。我們知道擲骰子得到點數 6 的機率為 1/6;那麼,如果問題是沒有得到 6 的機率為多少呢?很簡單,答案是 5/6。假設我們以反向機率計算點數 6 出現的機率,也就是以總機率減掉沒有出現點數 6 的機率:1 – 5/6 = 1/6 ,同樣地能夠得到正確的答案。

反向機率在計算複雜的條件情況時非常有用,例如:「擲骰子 6 次,至少得到 1 次點數為 6 的機率有多少?」題目是至少得到 1 次點數為 6 的結果,表示在出現 1 次、2 次、3 次、4 次、5 次與 6 次 的情況下,都要分別計算出機率,然後相加才是問題的答案。如果使用反向機率的概念,就只需要求出「沒有出現任何點數為 6 的機率即可」。擲 1 次骰子,沒有出現 6 的機率為 5/6;而擲 6 次骰子,沒有出現 6 的機率就是 (5/6)^6。所以,在這裡只要以總機率 1 減掉沒有出現點數為 6 的機率 (5/6)^6,就能夠輕鬆地得到問題的答案為 1 – (5/6)^6 = 67%。

在電腦科學中,關於程式的亂數產生器 (Random Number Generators),你所應該知道的事實:

程式領域中的亂數產生器,所產生出來的數值並不是真的亂數!事實上,多數亂數產生器只是一個非常龐大的數列,用以模擬出近似於亂數的結果。亂數產生器的演算法,需要使用者提供的「種子數目」(Seed Number) 以做為產生亂數數列的基礎依據。

在多數的情況下,程式設計者會直接取用 CPU 提供的時間值做為亂數種子,產生出遊戲中可以接受的亂數結果。但是在需要高度亂數結果的情境下,只是達到這樣的成果並不足夠;例如在賭場中的電子遊戲機或撲克牌遊戲,這樣非常頻繁使用亂數的系統中,就需要使用更嚴謹的亂數產生模型,才能夠免於被玩家抓到竅門而輸到破產關門的命運。

閱讀到這裡,是不是重新找回了一些對於「機率」這玩意兒的遙遠回憶?最後,關於前面三個謎題的解答:

  • 掉寶機率:以反向機率回頭檢驗兩個測試者的結果,有 10% 的機率得到寶物,等於是 90% 的機率無法得到。所以在 20 次的殺怪過程中,1 個寶物都沒有得到的機率就是:1 – (0.9)^20 = 12.2%。在 10% 機率的條件設定之下,可以計算出在 20 次的殺怪過程中,得到 4 個或 4 個以上寶物的機率為 13.3%。以上述兩個情況來看,都存在著一定的發生機率,所以並不能斷定是程式層面的異常問題,而是需要蒐集更多的測試資料加以比對,才能夠確認是否為程式層面的問題。
  • 致命傷害:以條件機率事件計算,至少得到 2 倍以上的傷害值的機率為:0.75 x 0.75 = 56.3%;而得到 4 倍以上的傷害值機率為 (0.75)^4 = 31.6%。玩家將近有 1/3 的機會能夠在攻擊中獲得 4 倍以上的傷害,哇!是時候該修改你的攻擊機制與傷害機制了!
  • 投擲硬幣的歷史紀錄:即使你提供給玩家過去 20 場的歷史紀錄,也完全不會改變硬幣出現正反面的機率仍舊是 50/50 的事實!如果玩家覺得過去十數場中出現極高比例的正面,因而決定下注大量的籌碼在反面的結果上,反而會使他們自己落入前述的賭徒誤謬陷阱之中,而越輸越多籌碼。(現在知道那些賭場的手法了吧?噓~不要講出去喔!XD)

以上這些機率的概念,真的是非常有趣而且又兼具實用性。閱讀完這篇文章之後,應該多少能喚回一些基礎的機率知識,也可能現在才會懊悔以前沒能認真學習機率論與統計學的課程吧(我自己先舉手 ._. /)。所以,做為稱職的遊戲企畫,或是未來想做出超強超讚超好玩遊戲的學生們,請敞開心胸學習更多有用的數學知識與數值分析方法,才能夠設計出真正平衡而且好玩的遊戲機制!

15 Replies to “《Statistically Speaking, It’s Probably a Good Game, Part 1》:遊戲設計者的基礎機率入門”

  1. 唔,剛剛拿小算盤算了一下,20次打怪沒收到寶物的機率為0.9^20 ~= 12.16%左右這機率其實還是挺高的,如果這個寶物在遊戲中佔有重要地位,這12.16%確實有必要作個調整。

    半路:
    以重要的寶物來說,這樣的機率設定的確是太高了。
    不過如果是一般任務的任務道具,例如某任務要打到 5 個哥布林頭,這樣的機率設定或許就差不多囉。

  2. i龍8部 黃金盾 
    http://erc16a.spaces.live.com/blog/cns!6FC3160701EB7C6B!724.entry

    i龍8部 黃金盾 
    為世界 祈求 新的和平 喲!
                           Δ 

                           Φ  = i 

                           ν

    Peace  = Πεαγε = πΕΑΣΕ  <-> 龍王號的  燈龍劍  = 上

    半路:
    請問這是什麼意思?
    和這篇文章有什麼關連性嗎? = =a

    (已刪除你前一篇不完整的留言)

  3. 如果事件發生的機率不是很低的話我都習慣用shuffle(洗牌)的方法代替random(亂數), 然後按照順序一張張抽牌
    但是第一個sample的位置一定要random否則使用者可以推測剩下的sample的值
    不是真的random, 但是designers like it.

    半路:
    原來如此,的確是個好方法呢!

    所以是在整組數列按照順序使用完畢之後,才重新進行 shuffle 嗎?

    用這樣的做法,就能夠控制事件在一定次數之內所發生的比例,
    而不會由於亂數機率的不穩定情況,產生出偏差值太大的結果。

    感謝提供意見與做法,
    能夠學到新的亂數設計方法真是開心~ :D

  4. 我計算了一下,謎題一第二個題目(殺20隻怪掉四個寶物)的機率應該為 0.0897。
    查了一下文章所引的原文,發現原題目問的是「殺20隻怪掉四個”以上”寶物的機率」
    (…then the chances of finding “at least” 4 ONH in 20 tries is 13.3%… – at page 7)

    原文提到謎題一第二小題的解法是透過機率的二項分佈(Binomial Distribution)來計算的,
    不過由於題目中的數字不大(只有四次),所以也可以透過高中數學中的排列組合與計算機來計算。
    話說回來,不知道現在高三的教材中還有沒有排列組合與機率等課程?

    這一篇文章的主題很有趣也很有意義,很值得遊戲開發人員深入了解。 (Y)

    半路:
    感謝提出正確版本的謎題題目,內文中的敘述已更正~
    之前的確是疏忽寫錯了。 Orz

    除了原文中提到的 Binomial Distribution 之外,
    這裡其實也可以利用反向機率來計算:
    1 – (得到 0 個 + 得到 1 個 + 得到 2 個 + 得到 3 個)
    的機率值所得出的結果,就是得到 4 個寶物以上的機率囉~

    高中應該還是有教機率與統計的相關課程吧?
    有沒有人可以出來證實一下的? XD

    感謝你的回應喔。 :D

  5. 是的, 牌發完後才重新洗牌才能控制機率. 之前忘了說 :P

    印象中高中數學好像有稍微提到機率但是沒有真正教機率的課程…
    統計學我確定是大學以後才教. 不過這是好久以前的事了, 說不定現在高中的數學就這麼深…

    半路:
    這個方法真的很不賴哩。
    我正在想要怎麼帶給我們家的企畫用。 XD

    我(很久)以前在高中的時候確定有學過排列組合,
    還有期望值、標準差、變異數這些基礎的統計方法(這是下一篇的主題),
    不過這是好久以前的事了,說不定現在的高中數學比較淺? XD

  6. 引述 R2D2「但是第一個sample的位置一定要random否則使用者可以推測剩下的sample的值」

    不明白為何要再找一個”random”的位置開始。Shuffle的過程是”random”的話,就無需要這樣吧?

    另外,Shuffle 的壞處是它會把 Gambler’s fallacy 變成有效,因為玩家能從之前的結果推算餘下的概率,所以不應該用來代替產生 sampling 的方法。Shuffle 就等於從袋子隨機拿東西後,不把它放回去。而之前說的 sampling 方法 是每次隨機拿東西後會把東西放回袋子。在遊戲中兩個做法都很有用,但不能互換,要按遊戲設計而選擇。無論是那一種隨機方法,我認為遊戲應該讓玩家知道「遊戲規則」。

    半路:
    我認為 Shuffle 的方式,就是要在「玩家不知道遊戲機制使用 Shuffle 取值」的情況下才能發揮效果啊!

    如果玩家都知道了遊戲機制是使用 Shuffle 而非真的 Random 方法,就會造成嚴重的機制失衡問題。Shuffle 與一般的 Random 方法都各有利弊之處,但是如果能混用兩種方法,使玩家無法輕易找出破綻,就能夠達到成效更佳的亂數機制設計。

    感謝您的意見。 ^^

  7. @Ricky:
    你好,

    我認為採用 random shuffle 的方式,能夠提供非常 stable 的假亂數結果,但前提是必須在玩家沒有察覺到,而且不破壞遊戲平衡的狀況下使用。random shuffle 可以說是一項相當實用的暗招密技呀~ XD

    謝謝你的回應。 ^^

  8. 回覆Milo大
    其實第一個sample的位置random就是為了降低gambler’s fallacy的影響
    從之前的結果推算餘下的概率的一個很重要先決條件就是玩家必須知道還剩下多少sample
    把第一個sample的位置random可以損壞這個前提

    要更”亂”一點還可以在reshuffle頻率上動手腳

  9. @路過:
    你好,
    歡迎你提供想法意見,或是其他相關的內容喔~

    謝謝。 ^^

    EDIT:
    我發現我好像誤解了。 XD

    你是希望我提供一些關於機率測試方面的相關內容嗎?你所謂的機率測試,是指如何驗證設定的機率是否正確嗎?如果是的話,我會再想看看可以寫些什麼有用的資訊~

    如果有任何想法或意見,還是一樣歡迎提供喔。 XD

  10. 是的大大!~
    有點想要了解這部份的資訊
    畢竟軟體的測試方面的書籍很少
    大部分都是英文的
    所以想藉由您這邊的見解做一下了解

  11. @路過:
    OK,我瞭解你的要求了。不過我目前對於測試方面的主題,還沒有比較完整具體的想法能夠寫成一篇文章,所以你可能需要先耐心等候一陣子囉。

    有一點倒是可以先稍微提一下。關於機率設定這種屬於數值層面的測試,最好是能夠由程式設計者寫出自動化的測試程序,自己重複執行個幾萬次以上,然後將結果記錄下來,後續再進行檢查與比對。這樣做不僅能夠減輕企畫設計者的負擔,也可以得出比較精確的驗證成果。

    謝謝你提出的意見。 :)

  12. 1 個寶物都沒有得到的機率就是:1 – (0.9)^20 = 12.2%<–應該改成:1 個寶物都沒有得到的機率就是: (0.9)^20 = 12.2% 不需要用1去減

Leave a Reply