看板 TypeMoon 關於我們 聯絡資訊
先講一個概念 不論是方法一 (卡片在伺服器端早已序列產生好) 或方法二 (伺服器端即時產生亂數,再依照亂數大小生成卡片) 如果你使用的是「真亂數」 那麼,不論是用什麼樣的方式去生成抽卡結果 那對抽卡的人來說 期望值都不會有影響 1%的機率長期統計下來仍然是1% 會有影響的,是抽卡結果的常態分布 例如,方法一可以避免「連續N單大暴死」 以及「十抽十五星」這種狀況發生 所以,擔心被領石帳/工作室搶走的假設 完全是多餘的 因為對方也可能幫你把槓龜的卡通通抽走 一來一往,等於沒影響 接下來會針對兩種方式做更仔細的解釋跟分析 可能會有點無聊 方法一: 卡片在伺服器端早已序列產生好 這就像是聖誕刷箱抽襪子,從一個固定的卡池抽獎的概念 這裡先聲明 卡池的大小並不一定要能包含所有卡片 因為再生成卡池的時候,也可以使用亂數 例如可以生成一百張卡的卡池 其中那一張五星卡,隨機決定是哪一張五星等等 另外關於池的大小也是一個問題 當你的池子數量太大的時候,等於沒作用 例如以1000抽為一池 依然可能發生900抽沒五星,最後100抽10五星這種狀況 所以如果有用卡池功能的話 這卡池的數目不能太大 卡池又有分,多人(全伺服器或單一伺服器節點)共用一個卡池,以下稱公池 或是個人獨立的卡池,以下稱個人池 如果是個人池 那麼,這種設計主要是避免「連續N單大暴死」或是「十抽十五星」 這種狀況發生 但很顯然FGO沒這麼做 為常常聽過有幾百抽0五星之類的狀況 或是十抽好幾隻五星的狀況出現 如果是公池 那沒有討論的必要了 在一大堆人共用卡池的狀況下 跟方法二的效果是一樣的 方法二: 伺服器端即時產生亂數,再依照亂數大小生成卡片 這個太簡單,我不知道該怎麼解釋 總之就是丟骰子那樣的模式 每次抽卡都等於是丟一次100面骰,丟中就中獎 接下來講關於程式的部分 方法二在實作上是最簡單的方案 就叫系統生成一個亂數,再用亂數去查表 他們應該會有一個設定檔案,決定了卡池的機率,記錄了每張卡的機率是多少 再用那張表,決定該生成什麼卡片出來 這種程式不需要考慮其他節點,或是各種鎖定、同步問題 所以說這是最簡單的方式 方法一,在實作上比較麻煩一點 如果是個人池的話,你需要去儲存他的卡池狀況 在他下次抽卡時,再拿出看看要給他什麼卡 如果是公池,那是非常麻煩的事情 如果A、B兩個人同時抽卡的話 你需要考慮兩者的執行緒安全問題 因為這可能會導致A、B兩個人都抽到同一張卡 這個bug在抽卡上造成的影響,聽起來好像沒什麼 但如果用購物網站來當例子的話..... 商品的數量只剩下1個 A、B兩個人同時按下結帳,結果兩個人都同時成交了。 大概是這種層級的問題 所以,實際上在寫這段程式碼的時候要這樣: 1. A鎖定卡池 2. A抽卡 3. A釋放卡池 B要等A把1~3都做完,才能抽卡 同一時間可能有幾百,甚至上千上萬人在抽卡 每個人都要一個個排隊、抽卡 這對伺服器來講是吃力不討好的工作 而且沒有必要搞成這樣 同樣的道理,把亂數交給第三方也只是把系統搞得更麻煩,更複雜而已 另外關於這個影片 https://youtu.be/Nehvzf9esQs
發生的原因可能是這樣 有些程式語言中的亂數 在初始化的時候要給他一個seed 而同樣的seed會導致生成同樣的亂數數列出來 而程式設計師給他的seed 是用「時間」,而且單位只到「秒」 例如php當中就是 srand(time()); 這樣 這會導致同樣時間點擊抽卡 抽到的卡都一樣的狀況 我的工作雖然不是轉蛋遊戲 但也是線上機率遊戲,跟遊戲、機率有扯上點關係 像這種機率遊戲,常常會有人懷疑站方作弊 或是在機率上動手腳 但營運單位才不會搞這種麻煩事 因為規則上就已經寫白了 營運單位就是要賺你的錢 拿大樂透來舉例 如果你看得懂遊戲規則的話 你就能看出「買一張大樂透平均下來會損失20元」這件事情 但還是有人會去賭 所以在評估「最差的狀況」的時候 基本上拿營運方公告的數值下去估算就可以了 以FGO來講,就是「真隨機,1%SSR」 轉蛋遊戲跟線上機率遊戲,有本質上不一樣的地方 轉蛋遊戲的營運方跟玩家的對立,不像線上機率遊戲那樣強 反而是,防止極端值出現,比較能避免玩家棄坑 這也是為什麼B服之前搞了個120抽保底出來的原因 像是保底機制,比較有可能的實現方法 就是在沒抽中的時候,在他個人紀錄上+1 當這個紀錄超過某個數值的時候,偷偷調高抽卡機率,這樣 B服那時候的狀況是直接設成100%,所以看起來很明顯 這種做法比個人池的方式,還要來的簡單方便的多 我認為在推斷卡池的機制的時候 應該要把日服跟B服分開來看 嘛.... 因為B服有前科 -- -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 125.227.87.115 ※ 文章網址: https://www.ptt.cc/bbs/TypeMoon/M.1507259943.A.B30.html
LayerZ: B服很久以前就有在做人工保底了=w= 10/06 11:22
LayerZ: 其實1跟2的差別只在於1抽完有沒有把卡放回去 10/06 11:22
officeyuli: http://www.sfoxstudio.com/10499 10/06 11:22
officeyuli: 水庫可以看看這個 10/06 11:22
aduijjr: 好複雜,就想成50%就好了阿XD 10/06 11:25
fatdragonz: 台服的資料來自B服, 所以台服也有可能有保底機制?? 10/06 11:26
sakeru: B服150抽泳裝爆死~~~ 保底一去不復返 10/06 11:26
sb8888: 想成0%就好了抽中的都不會是你 10/06 11:26
LayerZ: 阿,我說的B服不是指陸版,是指大陸手遊 10/06 11:27
hollowland: 方法一的鎖卡池(執行緒).. 嗚我的頭好痛... 10/06 11:27
zerox123456: 保底是好文明 10/06 11:30
LayerZ: 所以說1的作法是bullshit 抽個卡不會搞成這樣.. 10/06 11:31
officeyuli: 會啊 1.做法的好處就是有人來查時機率一定一樣啊 只 10/06 11:36
officeyuli: 是讓玩家等個執行緒而已也不會很久啊 10/06 11:36
LayerZ: 保底機制最簡單的作法,紀錄沒抽中次數,超過後換個只有四 10/06 11:37
LayerZ: 星的池給你,然後歸零 10/06 11:37
LayerZ: "只是讓玩家等個執行緒而已" (燦笑 10/06 11:37
LayerZ: 我豆頁痛 10/06 11:38
officeyuli: 又不是沒等過 怎麼了嗎 10/06 11:38
juju6326: 不用多,想想看有一千個玩家衝進來要等執行緒時會怎樣 10/06 11:39
officeyuli: 超過就炸伺服器啊 這不就是fgo嗎 10/06 11:40
LayerZ: 這種東西理論上在大次數(來個一億抽) 機率會一樣啦 10/06 11:40
LayerZ: 所以不用特地作1來防別人查 10/06 11:41
shintz: 看了下來還是覺得有保底跟天井好一點點 10/06 11:41
LayerZ: 自己東西出去前就會做這種測試了 10/06 11:41
shintz: 不然就像現在日版SIF搞個200抽box,把內容物剩餘數量都 10/06 11:42
shintz: 標示出來讓人流口水 10/06 11:42
ts1993: ('・ω・')那跟遊戲王的卡包一樣啊 10/06 11:43
torrot: 現在10抽有保底阿(欸 其實我覺得可以用個30連抽保4星從者? 10/06 11:43
officeyuli: 那是一番賞嗎 10/06 11:43
torrot: 有保底或是天井機制總是比較好的 10/06 11:44
fate201: 把抽個卡搞成mutex也太搞剛XD 10/06 11:58
nightcrow: 很遺憾的是保底已經不復存在了 10/06 12:00
faruz04: 保底120抽超佛的,1.2倍期望值就保了 10/06 12:03
dansy: 實際上機制1也無法防止個人N單暴死 因為共用卡池隨時在變 10/06 12:03
dansy: 十抽十五星的狀況就要看卡池箱子大小 夠大也不是不可能@@ 10/06 12:04
dansy: 如果要真的做到常態分佈 那實際上就會調整 而不是真隨機 10/06 12:09
sbd0517: 滿好奇十連保底的機制~ 10/06 12:10
wsgg25482: 120保底的期望值大概比1.2再高一點 因為還要考慮前面的 10/06 12:10
wsgg25482: 機率 10/06 12:10
dansy: 所以才需要驗證機制來取信說服玩家 避免黑箱疑雲 10/06 12:10
chuegou: 我在這裡宣布 哲學家用餐問題正式改名為御主抽卡問題 10/06 12:15
sai4311: 10連保底的機制並不難,只要排列成任意取10組必SR即可 10/06 12:18
e5a1t20: 御主抽卡問題www工程師可不會沒事自找麻煩 10/06 13:10
k0286: 當你的池子數量太大的時候,等於沒作用<< 不懂問題在哪? 10/06 13:14
twistedvate: (體感)當按下去佇列就排訂好哪些東西給你了,所以 10/06 13:15
twistedvate: 以才有換時段抽的說法 10/06 13:15
orze04: 個人池要看會不會update,不然就是偽機率了 10/06 13:19
orze04: 還要要看抽後是否放回 10/06 13:20
dderfken: 把你槓龜的抽走是你也抽很大才行啊 10/06 13:30
twistedvate: 佇列中100張卡就依機率塞卡,100張就一張五星隨機英 10/06 13:31
twistedvate: 然後再依你現有的酒桃量來切一段佇列給你抽 10/06 13:33
e5a1t20: 我覺得光是伺服器沒有爆,就足夠證明不會是先預先產生池 10/06 13:34
e5a1t20: 子了,100個執行緒同時搶一個記憶體空間,絕對塞爆 10/06 13:34
twistedvate: 這概念跟池子沒關,要查驗也沒問題(?) 10/06 13:34
twistedvate: *每100張卡 10/06 13:40
twistedvate: 每個請求剛好都沒切到那段含有五星英靈的佇列 就暴死 10/06 13:42
e5a1t20: 樓上不就要每人擺個100張牌,最近1000萬下載,嗯? 10/06 13:49
twistedvate: 就想像有個接近無限生成的長鏈的佇列等著大家切? 10/06 14:35
twistedvate: 拉長一算機率的確是對的 可是你切不到那段五星石頭 10/06 14:37
twistedvate: 石頭就抽光了 10/06 14:37
louis791021: 我的看法同樓上 10/06 21:56
twistedvate: XD 我只是體感猜測 10/07 01:46
twistedvate: 一次十抽內不知道會不會有三張五星? 目前只有看到雙 10/07 01:46
sameber520: 你要取的物事先在資料庫儲存沒有意義 做成公池沒必要 10/07 02:22
sameber520: 而且抽到卡片應該是產生以使用者區分的資料 10/07 02:28
sameber520: 如果先產生一個某從者的表單 然後玩家抽到就往裡面加 10/07 02:29
sameber520: 那PU的時候伺服器應該要爆 不然就是資料被覆蓋遺失 10/07 02:31