敲石头的技术帖(再发)
结论:敲石头的结果在敲石头的游戏被创建的时候就已经确定了,其他因素不影响在该游戏敲石头的结果,例如你换别的BB来敲,结果也一样。 就像一个游戏被创建之后,游戏的地图就确定了,不管你进来几个人、杀什么BOSS都一样
原文是我发表在TTBN的,其实1.11b的代码和1.10的代码基本一样的。如果你没有汇编知识或者编程知识,那就还是不要看了
发这篇文章的目的,是证明 其他所谓的秘诀都是扯淡~
原文地址:
http://www.ttage.com/bbs/viewthread.php?tid=134863这个不知道会不会被咔嚓掉,如果BB觉得不爽,就把它咔嚓掉吧。。。呵呵
我原来写的一篇文章,供有志者参考,不过需要较强的汇编语言知识。。。。。
文中需要反汇编工具IDA Pro。。。
老早就听说在Diablo2中使用了伪随机数来产生游戏行为的。今天在TTBN上听说有人能够在Rune Run中找到规律,能够敲出尽可能高的
符文。有许多人骂他是神汉~~汗。。。。
有关Rune Run最后的敲石头,就是完成A4的第二个任务,将有一个符文的奖励,在
地狱难度下面完成这个任务,可以获得15#~25#中的某个符文。网上大多研究表明,这个到底会得到那个符文,完全是随机的。。。
居然有人在此情形下,给出经验,说有把握能够敲到高级符文,怪不得变成人民公敌了。。
然后从理论的角度,由于D2里面是伪随机并不是真正的随机,因此完全有可能找到其规律,从而实现敲石头的时候,只出25#。
因此,我上网找了一下相关的资料,得到如下信息:
敲石头掉落的符文产生方法,是硬编码在d2game.dll中的。这个和别的物品掉落不一样,别的物品基本上都是由一个公共函数产生,几率由
配置文件(MPG文件)决定。
下面说的都是在Diablo2 1.11(其实D2 1.10的代码基本一样),也就是TTBN的文件上进行分析的。
1、首先要找到d2game.dll中,与敲石头任务奖励相关的代码。这个很容易,在d2game.dll里面搜索r25,就看到了,引用这个数字的地方,就是相关的代码;
2、在相关的代码片断,其任务奖励过程是:首先产生完美
宝石,然后产生无瑕疵的宝石,最后产生符文。
其中,完美宝石和无瑕疵的宝石产生极其类似,都是产生一个0~6的随机数,然后对应到相应的宝石即可。
3、符文的产生较为复杂。首先判断游戏难度,决定掉落的符文范围是多少?在普通难度,掉落的是1#~11#,而在噩梦难度,掉落的是12#~22#,地狱难度掉落的是15#~25#。
然后调用一个随机数函数,用于产生最终掉落符文的序号。最后根据这个序号产生对应的符文。
(见图)
而最为感兴趣的自然就是其中的随机数函数RuneRandom了。。其代码如下:
.text:6FC21040 RuneRandom proc near ; CODE XREF: sub_6FC336B0+187p
.text:6FC21040 ; sub_6FC41C20+CCp ...
.text:6FC21040 push esi
.text:6FC21041 mov esi, eax ; ESI=EAX=B
.text:6FC21043 test esi, esi
.text:6FC21045 jg short loc_6FC2104B
.text:6FC21047 xor eax, eax
.text:6FC21049 pop esi
.text:6FC2104A retn
.text:6FC2104B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:6FC2104B
.text:6FC2104B loc_6FC2104B: ; CODE XREF: RuneRandom+5j
.text:6FC2104B mov eax, [ecx]
.text:6FC2104D push ebx
.text:6FC2104E push edi
.text:6FC2104F mov edx, 6AC690C5h ; 初始化随机数种子
.text:6FC21054 lea edi, [esi-1] ; lea edi,[A]
.text:6FC21057 mul edx
.text:6FC21059 xor ebx, ebx
.text:6FC2105B test edi, esi
.text:6FC2105D jz short loc_6FC21075
.text:6FC2105F mov edi, [ecx+4]
.text:6FC21062 add eax, edi
.text:6FC21064 adc edx, ebx
.text:6FC21066 mov [ecx+4], edx
.text:6FC21069 mov [ecx], eax
.text:6FC2106B xor edx, edx
.text:6FC2106D div esi ; ESI = A = 10
.text:6FC2106F pop edi
.text:6FC21070 pop ebx
.text:6FC21071 pop esi
.text:6FC21072 mov eax, edx
.text:6FC21074 retn
.text:6FC21075 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?
.text:6FC21075
.text:6FC21075 loc_6FC21075: ; CODE XREF: RuneRandom+1Dj
.text:6FC21075 mov esi, eax ; EDI=ESI
.text:6FC21077 mov eax, [ecx+4]
.text:6FC2107A add esi, eax
.text:6FC2107C mov eax, edi
.text:6FC2107E adc edx, ebx
.text:6FC21080 pop edi
.text:6FC21081 pop ebx
.text:6FC21082 mov [ecx], esi
.text:6FC21084 and eax, esi
.text:6FC21086 mov [ecx+4], edx
.text:6FC21089 pop esi
.text:6FC2108A retn
.text:6FC2108A RuneRandom endp
可以看出,它使用的是一种典型的伪随机数产生算法,可以参考
http://www.luocong.com/articles/show_article.asp?Article_ID=24 简单的说,就是用如下公式产生:
Rand_Number = (Rand_Seed * X + Y) mod Z
其中Rand_Seed固定是6AC690C5h, 而Z固定是11
因此,决定最终随机数的只有X和Y。
不幸的是,X和Y并不能简单的推算出来。。。
它的XY大概的产生过程是:
1、貌似系统初始的时候,有一个XY,这个称为游戏种子,貌似是真随机的;
2、以后,每次使用随机数算法,将X更新为X*Rand_Seed + Y的高半部分;而Y更新为 X*Rand_Seed + Y的低半部分。相关算法如下:
mov eax, rand_h ; [ebp+0D0h]
mov ecx, 6AC690C5h
mul ecx
mov edi, eax
mov eax, rand_l ; [ebp+0D4h]
xor ecx, ecx
add edi, eax
adc edx, ecx
mov rand_l, edx ; [ebp+0D4h]
mov rand_h, edi ; [ebp+0D0h]
姑且将上述代码称为函数rand_step。
D2在最开始的时候首先生成随机数种子,然后使用这个种子不断的调用rand_step,每次调用,将更新这个随机数种子为一个新的值,然后D2再使用这个随机数去产生游戏行为,其中包括地图生成以及敲石头的结果(初始的种子经过数次rand_step之后,就是敲石头的结果了)。。。。
所以结论就是,在地图和敲石头结果之间存在联系,但目前联系还不清楚。有人说,下面的地图形状比较容易出高级RUNE,可能是有道理的( 我在单机上通过IDA Pro测试过一部分得到25#的地图,有许多地图和给出的地图形状基本一样)。