爐石溢出和最值研究
【真】疊最厚的甲,【真】挨最毒的打。實(shí)驗(yàn)了各種溢出:血上限、攻擊力、生命值、治療量、傷害值、護(hù)甲值。并得出結(jié)論。

(本文轉(zhuǎn)自旅法師營(yíng)地,是同一作者。原文鏈接https://www.iyingdi.com/web/article/search/68309)
簡(jiǎn)介
大家好,我是辣雞土豆,是之前“暗影狂亂計(jì)算器”的作者。(https://www.iyingdi.com/web/bbspost/detail/1806541)
眾所周知,爐石里的數(shù)值是有限的,當(dāng)你企圖通過周卓刷翻倍生命值,到達(dá)21億左右的時(shí)候,再增加就會(huì)歸零。我們稱之為“溢出”了。本文介紹什么是溢出、為什么會(huì)溢出,并結(jié)合實(shí)例分析多種溢出方式。
如果你對(duì)原理不感興趣,只希望看看溢出爽一下,可以直接看B站視頻。https://www.bilibili.com/video/av40449869
結(jié)論
由于大部分人可能對(duì)原理并不感興趣,先說實(shí)驗(yàn)結(jié)論:
1.爐石傳說里大部分?jǐn)?shù)值是int32(關(guān)于什么是int32,可以閱讀“什么是int32”部分)
2. 如果變量可以是負(fù)數(shù),int32超限時(shí)按補(bǔ)碼溢出,但顯示為0 (關(guān)于具體溢出方式,可以看“什么是溢出”部分);如果變量不允許是負(fù)數(shù),溢出置零。(攻擊力允許是負(fù)數(shù),法力消耗允許,生命值允許,已損失生命值不允許,生命上限不允許,護(hù)甲不允許。)
3.顯示零攻擊的單位無法攻擊,零點(diǎn)血量的單位直接結(jié)算死亡。顯示為0的負(fù)數(shù),只有在加減等數(shù)值運(yùn)算時(shí),按負(fù)數(shù)運(yùn)算,但負(fù)數(shù)總顯示0。
?
如果你沒有看懂上述3條,可以先看下文例子。
?
名詞定義
(為什么這樣定義見原理部分)
隨從雙維、隨從身材:指隨從的攻擊力和血
爐石上界: 爐石傳說中,最大的整數(shù),即2147483647
爐石下界:爐石傳說中,最大的整數(shù),即-2147483648
Int32:32位有符號(hào)整型數(shù)
?
數(shù)值溢出實(shí)例分析
1.血量上限溢出
實(shí)驗(yàn):使用神圣之靈不斷翻倍隨從血量。
現(xiàn)象:隨從血量不斷上漲,直到超過爐石上界的時(shí)候,歸零。并立即結(jié)算隨從死亡。
?(這個(gè)事情大家應(yīng)該都知道,不放圖了)
實(shí)驗(yàn):對(duì)血量上限是爐石上界的隨從使用香蕉。
現(xiàn)象:隨從血量歸零。并立即結(jié)算隨從死亡。
?
推測(cè)結(jié)論:爐石變量是int32
2.護(hù)甲值溢出
實(shí)驗(yàn):一個(gè)疊甲到爐石上界的戰(zhàn)士,再疊兩點(diǎn)護(hù)甲。
現(xiàn)象:最厚的甲再girashi的咆哮中變成了零護(hù)甲。
結(jié)論:護(hù)甲值是非負(fù)的,非負(fù)值溢出置零。
?

?
3.傷害值溢出
實(shí)驗(yàn):用一個(gè)雙維達(dá)到爐石上界的隨從,攻擊一個(gè)裝備了詛咒之刃的英雄。(挨最最最最毒的打)
現(xiàn)象:英雄沒有受到任何傷害。
結(jié)論:傷害值是非負(fù)的,非負(fù)值溢出置零。

4.治療量溢出
猢猻醫(yī)者會(huì)直接為一個(gè)隨從回復(fù)等于其血量上限的血,效果看起來就好像回滿血一樣。
水晶工匠坎格爾會(huì)讓回血效果翻倍。
?
實(shí)驗(yàn):我方場(chǎng)上有水晶工匠坎格爾,一個(gè)雙維(上限)達(dá)到爐石上界的光照元素,光照元素?fù)p失了1點(diǎn)生命值。我放打出猢猻醫(yī)者,為光照元素回復(fù)到滿血。
現(xiàn)象:猢猻醫(yī)者回復(fù)0血。
推測(cè):治療量本等于爐石上界,翻倍后溢出,溢出歸零。因而回復(fù)0血。
5.攻擊力溢出
實(shí)驗(yàn):使用神圣之靈使得隨從生命值正好達(dá)到爐石上界,并使用心靈之火使得隨從攻擊力等于血量。然后用叫囂的中士增加攻擊力使攻擊力+2,溢出。
現(xiàn)象:隨從雙維均達(dá)到最大,攻擊力+2后,隨從攻擊力顯示為0?;睾辖Y(jié)束后,隨從攻擊力-2,并變回了原數(shù)值。
分析:見實(shí)驗(yàn)原理,溢出部分。
推測(cè)結(jié)論:攻擊力是可以為負(fù)數(shù)的,不會(huì)因?yàn)橐绯觯ú皇钦龜?shù)了)而清零。
相關(guān)現(xiàn)象:被虛弱詛咒到負(fù)攻擊的隨從,在加攻擊力依然可能顯示為0。
損失血量溢出
實(shí)驗(yàn)一:對(duì)一個(gè)已經(jīng)損失了2點(diǎn)生命的紫羅蘭法師造成等于爐石上界的傷害。
現(xiàn)象:紫羅蘭法師回復(fù)到了滿血。
推測(cè):(2^31-1)+2>2^31-1,推測(cè)爐石傳說計(jì)算隨從血量時(shí)維護(hù)兩個(gè)數(shù)據(jù),一隨從的血量上限,二已損失血量。已損失血量超過爐石上界時(shí)自動(dòng)置為零,看起來就像沒有損失生命值一樣。
?
實(shí)驗(yàn)二:對(duì)一個(gè)滿血的紫羅蘭法師造成等于爐石上界的傷害。
現(xiàn)象:紫羅蘭法師正??垩?,死亡。
推測(cè):已損失血量沒有超過上界,所以不溢出,正常。
?



實(shí)驗(yàn)三:同理對(duì)地獄咆哮重復(fù)上述2個(gè)實(shí)驗(yàn)。
現(xiàn)象:英雄結(jié)算和隨從一樣。

?

結(jié)論:受到傷害時(shí),爐石代碼里可能是先計(jì)算“已損失血量”,如果不溢出,則當(dāng)前生命值=生命上限-已損失血量;如果溢出,由于“已損失血量”的非負(fù)性,則置零,然后,當(dāng)前生命值=生命上限-已損失血量,所以回滿血。
什么變量可以刷到溢出?
指數(shù)增加具有極高的效率。手動(dòng)+X/+X刷,刷到地老天荒也刷不到爐石上界。

理論上來說所有變量都可以刷到溢出(需要先配合無限時(shí)間)。只是有翻倍的道具的變量刷到溢出容易一點(diǎn)。如血量翻倍神圣之靈,攻擊翻倍受祝福的勇士?;蛘唛g接翻倍心靈之火等等。
?
?
實(shí)驗(yàn)原理
說明:如果對(duì)原理不感興趣,或者已經(jīng)學(xué)過,請(qǐng)直接跳過。
如果你想也做一遍實(shí)驗(yàn),或者想搞清楚,那么請(qǐng)全部閱讀“實(shí)驗(yàn)原理”。
原理部分假設(shè)你已經(jīng)學(xué)會(huì)高中的等比數(shù)列、指數(shù)運(yùn)算等相關(guān)知識(shí)。
1.什么是二進(jìn)制
簡(jiǎn)單的來說我們中小學(xué)學(xué)習(xí)的數(shù)字叫“十進(jìn)制”,就是逢十進(jìn)一,這主要是因?yàn)槿擞?0個(gè)手指。0數(shù)到9,在數(shù)就不夠用了,于是要“進(jìn)位”,變成10,我們定義它比9多1。十進(jìn)制里1021=10^3+2*10^1+10^0,每高一位代表的數(shù)乘十。同樣類比,二進(jìn)制里是這樣數(shù)數(shù)的:0,1,10,11,100,101……逢二進(jìn)一,二進(jìn)制的10001表示十進(jìn)制的2^4+2^0=17。
下文中,不做特意說明的地方,默認(rèn)十進(jìn)制,如果是二進(jìn)制,會(huì)在末尾加B,例如“1000 0000B”。
?
2.什么是補(bǔ)碼、什么是int32
因?yàn)橛?jì)算機(jī)只能存儲(chǔ)0101,所以整數(shù)在計(jì)算機(jī)里存儲(chǔ)時(shí),需要限定格式。補(bǔ)碼就是大部分整數(shù)在計(jì)算機(jī)里的格式,如果一個(gè)整數(shù)i,在計(jì)算機(jī)里占用8位(8bits=1B)那么補(bǔ)碼的規(guī)定如下:
第一位0表示非負(fù)數(shù),1表示負(fù)數(shù)
非負(fù)數(shù)后7位表示大小,例如0000 0001B=1、0111 1111B=127、 0000 0000表示0。
負(fù)數(shù)加對(duì)應(yīng)的正數(shù),應(yīng)該和是1 0000 0000B。例如-1=1111 1111B,那么-1+1=0表示為:1111 1111B +0000 0001B = 1 0000 0000B(簡(jiǎn)單的二進(jìn)制加法,逢二進(jìn)一,列豎式),由于計(jì)算機(jī)只能存儲(chǔ)8位,所以“1 0000 0000B”的最高位1,被計(jì)算器舍棄了,達(dá)到了-1+1=0的運(yùn)算。
特殊規(guī)定:“1000 0000B”表示-2^7=-128

8位補(bǔ)碼數(shù)據(jù)范圍:[-128,127] 共2^8=256個(gè)數(shù)
?

Int32就是32位的補(bǔ)碼,數(shù)據(jù)范圍 [-2^31,2^31-1] = [ -2147483648, 2147483647],所以我們稱這2個(gè)最值為:爐石下界、爐石上界
3.什么是溢出
溢出發(fā)生在當(dāng)數(shù)據(jù)大小超出內(nèi)存可以表示的范圍時(shí)。例如,你讓一個(gè)已經(jīng)是爐石上界(2147483647)的變量x,再增加1,就會(huì)溢出。表現(xiàn)為這個(gè)數(shù)變成了爐石下界(- 2147483648),這是因?yàn)橛?jì)算機(jī)里的二進(jìn)制數(shù)直接相加,加完以后符號(hào)位變成了1。同理,用爐石下界減去1,也可以得到爐石上界。


?

4.如何達(dá)到最大值2^31-1
本處只討論如何讓生命值上限達(dá)到2^31-1,心靈之火即可轉(zhuǎn)化為攻擊力,其他變量也可以通過各種方法轉(zhuǎn)化。
直接使用神圣之靈是不能達(dá)到爐石上界的,為了讓生命值達(dá)到爐石上界,我們需要復(fù)習(xí)一下等比數(shù)列通項(xiàng)公式:

所以只需要找到一個(gè)滿血且血上限是2^n-1的隨從,然后瘋狂讓它神圣之靈翻倍、吃香蕉,重復(fù)直到達(dá)到爐石上界即可!
?
結(jié)論復(fù)述
不知道你再看一遍這3句話,有沒有更深刻的了解了呢?
?
爐石傳說里大部分?jǐn)?shù)值是int32(關(guān)于什么是int32,可以閱讀“什么是int32”部分)
?如果變量可以是負(fù)數(shù),int32超限時(shí)按補(bǔ)碼溢出,但顯示為0 (關(guān)于具體溢出方式,可以看“什么是溢出”部分);如果變量不允許是負(fù)數(shù),溢出置零。(攻擊力允許是負(fù)數(shù),法力消耗允許,生命值允許,已損失生命值不允許,生命上限不允許,護(hù)甲不允許。)
顯示零攻擊的單位無法攻擊,零點(diǎn)血量的單位直接結(jié)算死亡。顯示為0的負(fù)數(shù),只有在加減等數(shù)值運(yùn)算時(shí),按負(fù)數(shù)運(yùn)算,但負(fù)數(shù)總顯示0。
?
?
?
?
實(shí)驗(yàn)感想
土豆的感想
在發(fā)了上次的群體狂亂計(jì)算器之后,蒸發(fā)君聯(lián)系了我,我們才彼此認(rèn)識(shí)。這個(gè)最值實(shí)驗(yàn)從我大一學(xué)習(xí)int32的時(shí)候就有想法了,時(shí)至今日已經(jīng)過了2年多了,其間做過多次實(shí)驗(yàn),前后有三四個(gè)小伙伴參與,甚至還有了爐石的翻倍的bug被我試了出來(現(xiàn)在沒了)。在蒸發(fā)君的慫恿和幫助下,我終于做出了完整的實(shí)驗(yàn),并得到了合理的解釋。
蒸發(fā)的感想
研究爐石的數(shù)值比上傳說還要好玩/
營(yíng)地老哥各個(gè)都是人才超喜歡這里的
Sorry,會(huì)點(diǎn)編程真的可以為所欲為。
(本文轉(zhuǎn)自旅法師營(yíng)地,是同一作者。原文鏈接https://www.iyingdi.com/web/article/search/68309)
土豆的小伙伴交流群:596948803
剪視頻真的累,希望大家多多支持。B站視頻:鏈接
寫在最后
本文是畢業(yè)前在營(yíng)地投稿的,此間發(fā)生了諸多事情:認(rèn)識(shí)了蒸發(fā)等人,混了營(yíng)地的稿費(fèi),被朝菌拉入【爐石科技】,結(jié)實(shí)茗凰等大佬,學(xué)習(xí)丟獸,拿到了b站的第一筆錢提現(xiàn),此后畢業(yè),進(jìn)入月圓之夜項(xiàng)目組實(shí)習(xí),最后回來讀研。此間有太多故事和經(jīng)歷,心態(tài)也經(jīng)歷了一些變化。之前就有人讓我把這個(gè)文章轉(zhuǎn)到b站,一直沒當(dāng)回事,現(xiàn)在發(fā)了一篇專欄,就順便轉(zhuǎn)一下。
本文在注明出處并給我留言(b站私信或其他)后,在不侵犯旅法師營(yíng)地權(quán)利的情況下可以任意轉(zhuǎn)載,不需要得到我的授權(quán)。