遊戲設計中有經典的計算公式

第一個問題:符文系統和天賦系統存在的必要性和對戰局的影響?

先引入兩個概念:
Ehp:effective health point 有效生命
Ehp受自身的HP、閃避、防禦、護甲、韌性、格擋、招架、免傷、技能係數、等級加成、各種抗性等等數值影響。
舉例:假如你有1W生命,且有50%減傷(與對方命中無關),那你的ehp就是2W。

Edps:effective damage per second有效輸出
Edps受自身的***力、命中值、暴擊率、暴擊效果、穿刺、急速、等級加成、各種屬性攻等等數值影響。
舉例:假如你的輸出間隔是1S,100%命中,***力爲100,暴擊率爲100%,暴擊效果爲150%,則你的edps爲150。

則在在兩個人之間的勝負結果,始終可以用下面的公式來表示:

所謂的符文、天賦、裝備等等各種系統,歸根結底都是對人物數值的影響,本質上並無任何區別,每新增一個系統,不過是把每個屬性的數值成長上限放高而已。所有以上沒有哪個系統是必要存在的,今天可以做成符文系統,明天還可以換成後宮加成系統,表現形式不同而已。至於對戰局的影響,最優解的問題會談到。




第二個問題:關於數值成長中最優解的存在
(開會去。。。晚點填)



==============================================================


ELO等級分體系
(很久之前做過的PPT,東西太多有點亂,粘一部分上來)

簡介


ELO等級分體系是根據它的推廣者埃洛(elo) 名字命名,它是一種以數值表示的體系,將等級差別轉化 爲分數或取勝概率。

理論基礎


粗略看一下很多比賽的成績表,能夠看出某個選手的表現是有起伏的,即有“狀態”之分。強手未必恆定表現好於弱手,每人之狀態在不同的日子不同的比賽裏都會有好壞不同。而總的來說整個生涯裏每一點上,一名選手的表現將大致圍繞在某個平均水平上下波動,有時會有背離,而出現大背離的情況比出現小背離的情況頻率要低。

於是,有了ELO體系的第一個假定:可以建立這麼一個等級量表,某個體在這個表裏的不同表現將正常分佈。

第二個假定簡單地說:在某一個特定的實力範疇裏,儘管可能存在實力上的差異,但總的來說可以預期沒有誰比誰好或差很多。由此可以定量劃分區間。

等級量表-區間尺度

等級差別是可能性方面的唯一重要因素。

指對陣雙方誰有多大機會勝/負/和,唯一影響因素在於他們之間的等級差別,這樣排除了難以確定的“狀態好壞”(第一假定),也排除了具體誰對誰的影響(第二假定)。

因此即使出現“爆冷”或 “剋星”,也視爲偶發情況,因爲ELO體系是建立在樣本足夠大量的統計基礎上的。

標準分類間隔(附表)

即某一個等級裏最高與最低之間的差別。在國際象棋裏,FIDE(即國際棋聯)採用每200分爲一個間隔的分類法,並且給每一個間隔取一個名字或排名以更好分辨。

常態分佈函數

強手未必總是勝過弱手,於是就使用一個“常態分佈函數來代表一名選手的波動表現,這是統計學上的概念。從這個函數裏可以得出另一個函數叫“常態概率函數” ,這個就定義了根據比賽對抗結果可得出的等級差別,或者根據已知的等級差別可得出的預期比賽對抗結果。它是這樣的:

P(D)這個值,就是以等級分差別D爲自變量計算出來的預期取勝可能性(預期得分率),它可近似用下面這個公式來計算:

舉例一

Ra:表示隊伍A當前的等級分
Rb:表示隊伍B當前的等級分
Sa表示隊伍A的比賽結果,勝利S值爲1,平局S值爲0.5,失敗S值爲0
Ea:表示A在這場比賽中的勝負值期望

Eb:表示B在這場比賽中的勝負值期望

其中Ea+Eb=1,也就是勝率和爲1

舉例二

一個等級分1950的選手,她的對手等級分1700分,那麼她取勝的機會有多大呢? 
等級分差別D=1950-1700=250,代入上面那麼近似計算公式,就是:

也就是說,她勝利的機會有80.8%,大約是81%。事實上,看下錶,即可得知等級分差別在246-256之間的強手預期取勝可能性就是81%。不用計算。

上面看不懂?沒關係!

 

當前等級分公式

Rn = Ro + K * (W - We)

Rn是賽事後的新等級分;Ro是賽事前的原等級分;K是單局得分的等級分點值,它是一個係數,取值有約定的;W是實際對局得分(勝得1、和得0.5);We是在原等級分基礎上的預期對局得分。 
這個公式是用來在連續基礎上(也就是每局或每個賽事之後)計算新等級分的。它把最新的表現調整考慮進先前的等級分中。它的邏輯意義是一個選手的表現高於他的預期得分以及低於他的預期失分。

係數K決定了事前等級分和本次表現分的相應權數。K值越高,那麼越近的賽事表現的分量越大。反之則反之。一般K值範圍從10到32。下面是一個K取值參考表:

舉例三

一個隊伍等級分1650,比賽中分別與等級分爲2050、1270和1550的三個隊伍對了陣,戰勝了低分的兩個,逼和了最高分的那個。問新等級分是多少?

K值取10;Ro=1650;W(勝2和1) = 1 + 1 + 0.5 = 2.5

We = P(1650 - 1270) + P(1650 - 1550) + P(1650 - 2050)
=0.910 + 0.638 + (1-0.921)
=1.627

套入第二個公式,即Rn = Ro + K * (W - We) = 1650 + 10 * (2.5 - 1.627) = 1659

也就是她在這次賽事後,等級分升了大約9分,成爲1659。

舉例四

某競技場隊伍等級分2350,11場比賽5勝6負,K取32;對陣11場情況如下:

已知原等級分Ro爲2350,已知本次比賽實際對局得分W=5,已知K值取32,已知(總)預期對局得分We爲5.24, 計算時可省略爲5.2,那麼根據公式(2),Rn = Ro + K * (W - We),新等級分Rn = 2350 + 32 * (5 - 5.2) = 2343.6 , 大約是2344,比之前下降了。

課後小思考


①K值如果往上取,會造成什麼情況?
②K值如果往下取,會造成什麼情況?
③WOW與DOTA天梯明顯的不同在什麼地方?
④以上的不同爲WOW帶來了什麼漏洞?
⑤WOW裏隊伍積分和個人積分分別有什麼用?

 

回覆:

1、卡馬克快速平方根

平方根倒數速算法

它讓計算平方根倒數的計算速度提高了4倍,導致了3D遊戲的革命。沒有這個算法,恐怕到現在3D遊戲裏的物體仍然沒影子(想想看CS的畫面)。

這個算法在上世紀就出現了,但是在10年前才引起遊戲圈的關注,算法的原理很清楚,但是作爲算法核心的那個常數,至今沒人知道它是怎麼得出來的。有傳言說是外星人***互聯網時留下了這個常數。遊戲業各位大牛紛紛在源代碼後面寫上了一句註釋:what the fuck?

 

在3D圖形編程中,經常要求平方根或平方根的倒數,例如:求向量的長度或將向量歸一化。C數學函數庫中的sqrt具有理想的精度,但對於3D遊戲程式來說速度太慢。我們希望能夠在保證足夠的精度的同時,進一步提高速度。

 

Carmack在QUAKE3中使用了下面的算法,它第一次在公衆場合出現的時候,幾乎震住了所有的人。據說該算法其實並不是Carmack發明的,它真正的作者是Nvidia的Gary Tarolli(未經證實)。

 

//
// 計算參數x的平方根的倒數
//
float InvSqrt (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i >> 1); // 計算第一個近似根
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x); // 牛頓迭代法
return x;
} 該算法的本質其實就是牛頓迭代法(Newton-Raphson Method,簡稱NR),而NR的基礎則是泰勒級數(Taylor Series)。NR是一種求方程的近似根的方法。首先要估計一個與方程的根比較靠近的數值,然後根據公式推算下一個更加近似的數值,不斷重複直到可以獲 得滿意的精度。其公式如下:

 

函數:y=f(x)

 

其一階導數爲:y'=f'(x)

 

則方程:f(x)=0 的第n+1個近似根爲

 

x[n+1] = x[n] - f(x[n]) / f'(x[n])NR最關鍵的地方在於估計第一個近似根。如果該近似根與真根足夠靠近的話,那麼只需要少數幾次迭代,就可以得到滿意的解。

 

現在回過頭來看看如何利用牛頓法來解決我們的問題。求平方根的倒數,實際就是求方程1/(x^2)-a=0的解。將該方程按牛頓迭代法的公式展開爲:

 

x[n+1]=1/2*x[n]*(3-a*x[n]*x[n])將1/2放到括號裏面,就得到了上面那個函數的倒數第二行。

 

接着,我們要設法估計第一個近似根。這也是上面的函數最神奇的地方。它通過某種方法算出了一個與真根非常接近的近似根,因此它只需要使用一次迭代過程就獲得了較滿意的解。它是怎樣做到的呢?所有的奧妙就在於這一行:

 

i = 0x5f3759df - (i >> 1); // 計算第一個近似根超級莫名其妙的語句,不是嗎?但仔細想一下的話,還是可以理解的。我們知道,IEEE標準下,float類型的數據在32位系統上是這樣 表示的(大體來說就是這樣,但省略了很多細節,有興趣可以GOOGLE):

 

bits:31 30 ... 0
31:符號位
30-23:共8位,保存指數(E)
22-0:共23位,保存尾數(M)所 以,32位的浮點數用十進制實數表示就是:M*2^E。開根然後倒數就是:M^(-1/2)*2^(-E/2)。現在就十分清晰了。語句 i>>1其工作就是將指數除以2,實現2^(E/2)的部分。而前面用一個常數減去它,目的就是得到M^(1/2)同時反轉所有指數的符號。

 

至於那個0x5f3759df,呃,我只能說,的確是一個超級的Magic Number。

 

那個Magic Number是可以推導出來的,但我並不打算在這裏討論,因爲實在太繁瑣了。簡單來說,其原理如下:因爲IEEE的浮點數中,尾數M省略了最前面的1,所 以實際的尾數是1+M。如果你在大學上數學課沒有打瞌睡的話,那麼當你看到(1+M)^(-1/2)這樣的形式時,應該會馬上聯想的到它的泰勒級數展開, 而該展開式的第一項就是常數。下面給出簡單的推導過程:

 

對於實數R>0,假設其在IEEE的浮點表示中,
指數爲E,尾數爲M,則:

 

R^(-1/2)
= (1+M)^(-1/2) * 2^(-E/2)

 

將(1+M)^(-1/2)按泰勒級數展開,取第一項,得:

 

原式
= (1-M/2) * 2^(-E/2)
= 2^(-E/2) - (M/2) * 2^(-E/2)

 

如果不考慮指數的符號的話,
(M/2)*2^(E/2)正是(R>>1),
而在IEEE表示中,指數的符號只需簡單地加上一個偏移即可,
而式子的前半部分剛好是個常數,所以原式可以轉化爲:

 

原式 = C - (M/2)*2^(E/2) = C - (R>>1),其中C爲常數

 

所以只需要解方程:
R^(-1/2)
= (1+M)^(-1/2) * 2^(-E/2)
= C - (R>>1)
求出令到相對誤差最小的C值就可以了上面的推導過程只是我個人的理解,並未得到證實。而Chris Lomont則在他的論文中詳細討論了最後那個方程的解法,並嘗試在實際的機器上尋找最佳的常數C。有興趣的朋友可以在文末找到他的論文的鏈接。

 

所以,所謂的Magic Number,並不是從N元宇宙的某個星系由於時空扭曲而掉到地球上的,而是幾百年前就有的數學理論。只要熟悉NR和泰勒級數,你我同樣有能力作出類似的優化。

 

上有人做過測試,該函數的相對誤差約爲0.177585%,速度比C標準庫的sqrt提高超過20%。如果增加一次迭代過 程,相對誤差可以降低到e-004的級數,但速度也會降到和sqrt差不多。據說在DOOM3中,Carmack通過查找表進一步優化了該算法,精度近乎 完美,而且速度也比原版提高了一截(正在努力弄源碼,誰有發我一份)。

 

值得注意的是,在Chris Lomont的演算中,理論上最優秀的常數(精度最高)是0x5f37642f,並且在實際測試中,如果只使用一次迭代的話,其效果也是最好的。但奇怪的 是,經過兩次NR後,在該常數下解的精度將降低得非常厲害(天知道是怎麼回事!)。經過實際的測試,Chris Lomont認爲,最優秀的常數是0x5f375a86。如果換成64位的double版本的話,算法還是一樣的,而最優常數則爲 0x5fe6ec85e7de30da(又一個令人冒汗的Magic Number - -b)。

 

這個算法依賴於浮點數的內部表示和字節順序,所以是不具移植性的。如果放到Mac上跑就會掛掉。如果想具備可移植性,還是乖乖用sqrt好了。但算法思想是通用的。大家可以嘗試推算一下相應的平方根算法。

2、簡單公式

減法公式:受到傷害=敵人***力-防禦力
除法公式:受到傷害=敵人***力*敵人***力/(防禦力+敵人***力)
乘法公式:受到傷害=敵人***力*(1-免傷率)
經典概率算法
圓桌概率算法
屬性池概念

3、雙曲線公式:COC中大量粗暴的使用

4、ELO算法:貌似wow和11平臺的天梯都有用到

5、超級機器人大戰傷害計算公式

{(武器***力×(對應能力值+氣力)×武器的地形適應÷200-裝甲值×(防禦值+氣力)÷200)×***機體地形適應修正}÷100×{100+(武器的最大射程-和敵人的距離)×3÷100}*特殊技能修正 

1L是正解,我是來解釋的。

武器***力,即***時選擇武器的列表中標示的***力。

能力值,如果武器是格鬥武器則是機師的格鬥值,若是射擊武器則是機師的射擊值,若是跨系武器則取兩者的較高值。

武器地形適性是指武器具體屬性中對應的“空宇地海”的那個,S爲1.2,A爲1,B爲0.8,C爲0.6(B和C不太確定……)

裝甲值,機體的裝甲數值,這個不用解釋吧……氣力是機師的氣力,防禦值是機師的防禦數值……機體地形適應修正指的是機體能力具體屬性中的對應的“空宇地海”的那個,參數與前面相同。“射程”不用解釋吧……特殊技能的修正指的是機師技能對傷害的影響,比如機師獨有的某些技能,以及強攻者等等技能的影響。

具體舉個例子:

我方某機體(機體的地形適性空S宇S陸A海A)用一種射程爲7、***力3000的光束射擊武器(光束武器一般都是空A宇A/S陸A海B)從水中射擊距離爲5的敵方1600裝甲值的機體。我方機師氣力150,格鬥210射擊190,有強攻者技能(氣力130以上傷害爲1.2倍);敵機師氣力100,防禦200。

此時我方***造成的傷害是{[3000×(190+150)×0.8÷200-1600×(200+100)÷200]×1}÷100×[100+(7-5)×3÷100]×1.2=2017

6、D&D中的各種檢定計算

7、卡馬克卷軸算法

8、仙境傳說:護甲值是def,體力值vit 受到的傷害=對方〔atk*(100-def)/100〕-vit 從兩方面減傷,同時強調了護甲值和加點體力的重要性

9、蘭切斯特方程式

10、火炎紋章系列亂數表


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章