究極綠寶石5.3——科普向,什么是金手指(四)
說在前面:
????上一期的專欄,作者介紹了映射表這個概念。從抽象的層面上來說,電子游戲中的一切都是數(shù)字;從具體的層面上來說,變量地址和變量取值的映射表是將游戲中的數(shù)字與實體聯(lián)系起來的橋梁。變量地址的映射表只有一張,而變量取值的映射表有很多。想要理解金手指的原理,需要從這些映射表入手。
????本期專欄還是討論“變量與實體的映射表”這個話題,使用VBA模擬器中“查找金手指”的功能,難度要比上一期更大。

查找金手指例3——隊伍首位精靈的個體值在哪里?
????玩精靈寶可夢系列游戲有一段時間的玩家都會知道,游戲中有精靈個體值的設定。每個精靈都有自己的個體值,從第三世代開始,分為HP、攻擊、防御、速度、特攻、特防,共六項,每項的取值是0~31。如果單項個體值是31(滿單項個體值),玩家們通常就稱此為V(道理是這樣的:將十進制數(shù)31轉換為三十二進制,三十二進制中,0~9仍然表示十進制的0~9,然后從字母A開始表示10,B表示11,……直到V表示31),例如“速度V”就是速度的個體值是31。有幾項個體值是滿的,就稱為“幾V”,例如六項個體值全滿就稱為“6V”,少了一項就稱為“5V”。很多玩家熱衷于孵蛋,其中有一個目的就是生出6V的精靈。
????在有些特定玩法下,也可能需要刻意拉低某項個體值,比如玩戲法空間的空間隊,希望速度的個體值是0,這時候可能就需要一個“0速5V”的精靈;比如特攻手希望受到“欺詐”這個技能的傷害越小越好,就想讓攻擊的個體值是0。
????在究極綠寶石5中,紫堇市的街頭有個人會給你看隊伍首位精靈的個體值;打敗茵郁市飛行道館門口的真嗣后,他會給主角一個能力值查看器,能夠查看所有精靈的個體值。我們現(xiàn)在的問題是:隊伍首位精靈的個體值,它映射到的變量地址是多少?
????掌握了第三期專欄中介紹方法的讀者,可能會自己嘗試一下,先用能力值查看器或者紫堇市街頭的那個人看一下自己精靈的某項個體值,然后在“查找金手指”的頁面中輸入這個個體值的數(shù)字,進行第一次查找。接下來把隊伍首位精靈換成另一個個體值不同的,然后再次在“查找金手指”內查找,看看是不是搜索的范圍縮小了。對本段內容還不熟悉的讀者可以回顧一下第三期專欄。
????很遺憾,這個方法對于搜索個體值的變量地址并不適用,原因就出在“搜索某項個體值”這個操作上。精靈共有六項個體值,事實上,這六個數(shù)字是放在一起的,單獨查找哪一個都找不到,因為其中的某個數(shù)字對應的變量取值既不是2位十六進制數(shù),也不是4位和8位的。對于“這六個數(shù)字放在一起”這句話究竟在數(shù)學意義上怎么理解,神奇寶貝百科給出了答案:
個體值由2位十六進制數(shù)(00~1F,即十進制下的0~31)表示,占用5位字段?!?/p>
在第三世代中,所有的個體值一起存儲在一段32位(4字節(jié))字段中,第一位決定了寶可夢的特性,第二位決定寶可夢是否為蛋的狀態(tài)(0為否,1為是),接下來的三十位依次決定寶可夢的特防、特攻、速度、防御、攻擊、HP的個體值。如果一只寶可夢只有一種特性,那么其對應字段首位就只會是0。
????這段話是神奇寶貝百科(https://wiki.52poke.com/wiki/)中,搜索“個體值”詞條所出現(xiàn)的頁面上的原文,信息量非常之大。之前不了解計算機知識的讀者,就算看到這段話,估計也會略過。但在我們看來,這簡直是官方的大福利??!官方把個體值的變量取值是怎么組織的詳詳細細地告訴玩家,那我們就按照官方的說明,把六項個體值“組裝”成一個變量取值。
????按照官方的說法,個體值“占用5位字段”,這句話的意思是說,單個個體值占用5個二進制位,原因非常自然,要表示0~31共32個取值,5位二進制數(shù)剛好夠用()。再結合下面這句:“所有的個體值一起存儲在一段32位(4字節(jié))字段中”,32位二進制數(shù)就是8位十六進制數(shù),于是我們知道了個體值的變量取值的長度,和上一期專欄中的金幣數(shù)是一樣的。最后,這句話“接下來的三十位依次決定寶可夢的特防、特攻、速度、防御、攻擊、HP的個體值”,更加自然,因為5*6=30,六項個體值,每項占5個二進制位,一共占30位。
????俗話說得好,“一圖勝千言”,把引用自神奇寶貝百科的話總結成一張圖,如下所示:

????這個數(shù)字來自于下圖的比比鳥,是作者臨時測試隨便抓的一只精靈:


????究極綠寶石5雖然整合了第一到第八世代的精靈和劇情,但本源還是第三世代的綠寶石,因此組織方式按照第三世代的來,讓我們依次分析這個32位二進制數(shù)(9dee7a69(16))是怎么組成的:
????最高位是1:按官方說法,“第一位決定了寶可夢的特性……如果一只寶可夢只有一種特性,那么其對應字段首位就只會是0”,這句話的意思其實說的是最高位決定了精靈是哪一個普通特性。比比鳥有兩個普通特性:銳利目光和蹣跚,分別對應到0和1。圖中的比比鳥是蹣跚特性,因此最高位是1。
????次高位是0:按官方說法,“第二位決定寶可夢是否為蛋的狀態(tài)(0為否,1為是)”,比比鳥現(xiàn)在當然不是蛋的狀態(tài),所以是0。
????下一個連續(xù)的5位:特防個體值,從能力值查看器上可以看到,比比鳥的特防個體值是14,用win10程序員模式的計算器(這個計算器在第二期、第三期專欄都用了好多次了,不會還有讀者不知道吧?)可以換算成二進制的01110(2),正好和圖片中的對應上。
????再下一個連續(xù)的5位,以及之后的個體值就交給讀者們自己驗證了。組裝好之后,我們就可以在“查找金手指”的頁面進行搜索:

????有兩點需要注意?!皵?shù)據(jù)尺寸”這里要選32位,因為要查找的變量取值是32位二進制數(shù)。另一個是“有/無正負之分”這里,之前的用法都是用的“不分正負”,這里用十六進制會方便一些,當然也可以先用計算器把9dee7a69轉換為十進制,再選擇“不分正負”。
搜索結果如下:

????有4個搜索結果,范圍已經(jīng)不是很大了,接下來我們需要“追蹤式變量取值查找”,對首位精靈的個體值做一下修改,然后繼續(xù)查找。修改首位精靈的個體值有個最簡單的辦法,就是把首位精靈換成別的精靈。作者再隨便抓一只飛天螳螂,“查找個體值”的界面果然發(fā)生了變化:



????新抓了飛天螳螂后,再次查找,也不需要點擊“查找”按鈕了,發(fā)現(xiàn)只有一個地址處的取值發(fā)生了變化,也不需要我們再根據(jù)飛天螳螂的個體值計算那個32位二進制數(shù)了,因為目標已經(jīng)找到:精靈個體值映射到的變量地址是02024534。

查找金手指例4——背包中的道具在哪里?
????上一期的專欄中,作者給出了一個隊伍首位精靈攜帶道具映射到的變量地址:0202450e。在這個例子中,我們要學會舉一反三,利用映射表的通用性,找到和道具相關的另一個實體——背包中的道具——的變量地址。
????映射表的通用性,指的是同一類游戲實體的變量取值的映射表,在不同的環(huán)境下保持不變。舉例來說,隊伍首位精靈的種族、野生戰(zhàn)斗遇到的精靈種族、隊伍第二位精靈的種族,用的是同一張精靈種族的映射表;精靈攜帶的道具、背包中存放的道具、電腦中存放的道具,用的是同一張道具的映射表;玩家的名稱、精靈的名稱,用的是同一張漢字的映射表……
????在這里,“隊伍首位”“野生戰(zhàn)斗”“背包中的”“電腦中的”“玩家的”“精靈的”描述的都是實體所在的環(huán)境,真正的實體是“精靈類型”“道具”和“漢字”。由于環(huán)境的不同,這些實體的變量地址也會不同,但它們對應的映射表是同一張。例如02b0在精靈種族的映射表中代表三首惡龍,那么02b0無論是在首位精靈的精靈種族,還是野生戰(zhàn)斗遇到的精靈種族,還是隊伍第二位精靈的種族,代表的都是三首惡龍。
????這就給我們提供了“舉一反三”的機會。在上一期的“自己動手來嘗試”環(huán)節(jié)中,如果有嘗試過的讀者,可能手里已經(jīng)有一些道具映射到變量取值的記錄了。我們可以利用幾個道具映射到的變量取值,來找到“背包中的道具”的變量地址。
????下圖為作者的一個存檔,打開背包,找到道具,一直拉到最上面:

????目前顯示,背包中攜帶的第一個道具是心之鱗片。通過上期的“自己動手來嘗試”,找到了心之鱗片映射到的變量取值是006f,我們打開“查找金手指”,“數(shù)據(jù)尺寸”選“8位”,“有/無正負之分”選擇“十六進制”,在下方輸入框內輸入006f,點擊“開始按鈕”,再點擊“查找”按鈕(這一系列操作,經(jīng)過了之前的例子,讀者們應該很熟悉了)。

????看起來結果很多啊。沒關系,我們還可以用“追蹤式變量取值查找”?;氐接螒?,用Select鍵把“紅色碎片”這個道具移到第一個道具的位置。如果不知道自己VBA模擬器里面Select鍵是哪個,可以到“選項——手柄——設置——1...”里面去設置,在“選擇”那一欄對應的按鍵就是Select鍵,作者用的是鍵盤上的退格鍵(Backspace),如下圖:

????在背包中,光標移到“紅色碎片”,然后按Select鍵,左邊會提示“移動紅色碎片去哪”。

????然后再按一次“上”鍵,再按一次Select鍵退出選擇,就把紅色碎片移到第一個位置去了:

????紅色碎片映射到的變量取值是0030,我們回到“查找金手指”界面,輸入0030,再次點擊查找,這次只剩下一個結果了:

????因此,背包中第一個道具映射到的變量地址就是0203d030。
????先別著急慶祝,做到真正的“舉一反三”還差一步。對第二期專欄還有印象的讀者,應該沒有忘記“變量地址查看器”這個東西,它還是我們驗證找到的變量地址是否正確的兩個驗證手段之一(另一個是看“查找金手指”里的“舊值”和“新值”)?,F(xiàn)在我們把“變量地址查看器”打開(工具——反匯編),輸入0203d030,然后點擊“轉到”按鈕:

????變量地址0203d030處,變量取值確實是0030,對應著紅色碎片。沒錯,看來我們找到的變量地址是正確的。我們繼續(xù)向下看,地址0203d032處,取值是0009,也就是十進制的9,這個9是什么含義呢?
????現(xiàn)在可以到上面再看一眼主角的背包,紅色碎片的數(shù)量恰好是9,這會不會是巧合呢?我們繼續(xù)向下看。
????下一個地址,0203d034處,取值是006f,這個數(shù)字剛才出現(xiàn)過,是心之鱗片映射到的變量取值,而心之鱗片恰好是背包里的第二個道具。
????再下一個地址,0204d036處,取值是0022,這是十進制的34,背包里心之鱗片的數(shù)量恰好是34。再往下可以一一驗證,依次是第三個道具的變量取值、第三個道具的數(shù)量、第四個道具的變量取值、第四個道具的數(shù)量……
????這個事實可以給我們什么啟發(fā)呢?
????第一個啟發(fā)是:為什么背包里面,道具的變量取值和數(shù)量在地址上是緊挨著放的?這其實是為了編寫程序的時候便于管理,把相關的、相似的變量放在一起,找起來的時候會更方便。因此在查找其他變量地址的過程中,我們也可以順著地址向上或向下看看,會不會有新發(fā)現(xiàn)。
????第二個啟發(fā)是:第三期專欄的“自己動手來嘗試”中,為了獲得每個道具映射到的變量取值,我們需要不斷地在游戲中替換首位精靈的攜帶物品,測試一百個道具,這個操作就需要重復一百次,十分繁瑣。而在這里,我們只需要利用“變量地址查看器”,就可以一次性獲取背包中所有道具映射到的變量取值。這在操作上是不是大大簡化了?
????希望讀者們能將這種“舉一反三”應用到其他地方去,讓做事的時候事半功倍。

查找金手指的方法總結
????第三期和本期專欄舉了很多“查找金手指”這一功能的例子,可以做個總結了。
????查找“修改變量取值”這一類的金手指,其本質是找到游戲內實體到數(shù)字的映射表,具體來說是找到從游戲實體到變量地址和變量取值的映射表?!安檎医鹗种浮边@個功能,對不同的游戲實體操作起來,方法大同小異。
????第一類:變量取值是純粹的數(shù)字。第三期專欄的例1——查找金幣數(shù),和例2——查找隊伍首位精靈等級,就都屬于這一類。除此之外、精靈剛被捕捉時的等級、玩家訓練師卡片上的ID、精靈面板上的數(shù)值(如當前HP、最大HP、特攻特防值等等)、對戰(zhàn)開拓區(qū)的對戰(zhàn)點數(shù)等,也都屬于這一類型,它們的特點是不需要變量取值的映射表,因為游戲實體本身就是數(shù)字。
????第二類:變量取值對應著不是直接由數(shù)字表示的游戲實體。第三期專欄給出的查找精靈類型的例子,和本期的例4——查找背包中的道具,就屬于這一類。除此之外,精靈攜帶的道具、精靈被捕捉的地點、玩家名稱/精靈名稱中出現(xiàn)的漢字/數(shù)字/英文字符/特殊字符、精靈被捕捉用的精靈球、精靈性格、精靈技能等,也都屬于這一類型。它們的特點是每一類實體都會有一張映射表,但是同類的映射表是通用的。
????第三類:變量取值是由聯(lián)系緊密的一系列數(shù)字在二進制下拼裝成的。本期給出的精靈個體值的例子,就屬于這一類。除此之外,精靈的努力值、精靈緞帶數(shù)、對戰(zhàn)開拓區(qū)的印記情況等,也都屬于這一類型。它們的特點是變量取值經(jīng)過了程序員的設計,通常是在二進制位上把表示每個實體的數(shù)值拼接在一起,而不是每個實體的數(shù)值用一個單獨的變量來表示。
????用一個流程圖的方式來描述“查找金手指”的功能如何使用:

????流程圖中,紅色的線代表變量地址的輸入或輸出,藍色的線代表變量取值的輸入或輸出。這是一個循環(huán)的過程,起點可以是“本身就是數(shù)字”的游戲實體,也可以是“網(wǎng)絡上金手指代碼的搜索結果”。在經(jīng)過驗證之后,新得到的變量地址或者變量取值可能有助于發(fā)現(xiàn)新的映射表。

自己動手來嘗試
????仿照“精靈個體值”的查找方式,嘗試查找“隊伍首位精靈努力值”映射到的變量地址,并明確6項努力值組成變量取值的組織方式??梢詤⒖嫉馁Y料在專欄的例子中都出現(xiàn)過,比如神奇寶貝百科、網(wǎng)上的金手指代碼等等。

????用了兩期專欄,算是把“變量與實體的映射表”這個概念在結合例子的情況下講了個大概。在手里有了一份基本完整的映射表之后,使用金手指也就是水到渠成的事了。不過金手指真的管用嗎?回顧第一期專欄結尾處提出的三個問題,我們還有最后一個問題沒有回答——修改變量的副作用,留到下期專欄介紹。
????還能堅持讀到這里的讀者們,謝謝大家的支持!