
标题: DOS版三国志英杰传的研究心得——陆 [打印本页]
作者:
漫漫苦短 时间: 2026-3-9 19:19 标题: DOS版三国志英杰传的研究心得——陆
上一章讲解了道具,并将其中的道具分解为6个大类,其中在“02攻擊用”“03恢復用”有部分道具是可以与部队所用的策略对应上,先按照道具的代码和策略代码对应列举如下。
策略代码 策略名字 道具代码 道具名字 分类
00 焦熱 28 焦熱書 火类
01 火龍 29 火龍書 火类
02 猛火 2A 猛火書 火类
03 大焦熱 / 无对应道具 火类
04 大火龍 / 无对应道具 火类
05 漩渦 25 漩渦書 水类
06 濁流 26 濁流書 水类
07 海嘯 27 海嘯書 水类
08 大漩渦 / 无对应道具 水类
09 大濁流 / 无对应道具 水类
0A 落石 22 落石書 石类
0B 山崩 23 山崩書 石类
0C 山洪 24 山洪書 石类
0D 大落石 / 无对应道具 石类
0E 大山崩 / 无对应道具 石类
0F 假情報 2B 濃霧書
10 偽兵 2C 雷陣雨書
11 偽裝 2D 豪雨書
12 牽制 / 无对应道具
13 挑撥 / 无对应道具
14 欺壓 / 无对应道具
15 激勵 1B 酒
16 支援 1C 特級酒
17 鼓舞 1D 老酒
18 援助 1E 豆
19 補給 1F 麥
1A 救濟 20 米
1B 看護 34 傷藥
1C 治癒 35 中藥
1D 救命 36 茶
1E 大激勵 31 平氣書
1F 大支援 32 活氣書
20 大鼓舞 33 勇氣書
21 大援助 2E 援隊書
22 大補給 2F 援部書
23 大救濟 30 援軍書
/ 无对应策略 21 炸彈
这些道具和策略都是类似的,根据道具使用的过程,可以分为3个阶段,(1)判定阶段,(2)计算阶段,(3)结算阶段,策略使用的过程也是可以分为以上三个阶段,而且在策略与对应道具的使用中所涉及到的代码,有相当多是重合的部分,也可以换一种方式理解,就是两者使用的过程调用同一个函数,但传入的参数不同,实现不同的结果。
接下来会同步写这两章的内容,有重复的部分会专门对比一下,也能更清晰看出其中的游戏的道具和策略不同的设计思路。
目录- 一、火水石类策略的使用(1)
- 二、火水石类策略的使用(2)
- 预告 三、火水石类策略的使用(3)
[ 本帖最后由 漫漫苦短 于 2026-4-9 19:20 编辑 ]
作者:
漫漫苦短 时间: 2026-3-31 19:19 标题: 一、火水石类策略的使用(1)
与道具的使用中的代码类似,对策略的使用前的判断也是通过策略的代码来将每个策略区分开。arg_2为策略代码。
seg002:A556 loc_37476: ; CODE XREF: sub_373EC+64↑j
seg002:A556 80 7E 08 0E cmp [bp+arg_2], 0Eh
seg002:A55A 76 03 jbe short loc_3747F
seg002:A55C E9 8C 01 jmp loc_3760B
seg002:A55F loc_3747F: ; CODE XREF: sub_373EC+8E↑j
seg002:A55F 8A 46 08 mov al, [bp+arg_2]
seg002:A562 B1 05 mov cl, 5
seg002:A564 2A E4 sub ah, ah
seg002:A566 F6 F1 div cl
seg002:A568 88 46 FD mov [bp+var_3], al
seg002:A56B 8A 46 08 mov al, [bp+arg_2]
seg002:A56E 2A E4 sub ah, ah
seg002:A570 F6 F1 div cl
seg002:A572 80 FC 03 cmp ah, 3 ; 判断是不是单体策略
seg002:A575 72 04 jb short loc_3749B
seg002:A577 B0 01 mov al, 1
seg002:A579 EB 02 jmp short loc_3749D
seg002:A57B loc_3749B: ; CODE XREF: sub_373EC+A9↑j
seg002:A57B 32 C0 xor al, al
由于从00-0E道具代码都是火水石类策略,因此只需要seg002:A556一个判断就行。然后就是seg002:A566除以cl(5),ah结果为除法运算的余数,al为除法运算的商,因此seg002:A568ah和al的结果如下表:
策略 00焦熱 01火龍 02猛火 03大焦熱 04大火龍 05漩渦 06濁流 07海嘯 08大漩渦 09大濁流 0A落石 0B山崩 0C山洪 0D大落石 0E大山崩
ah 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
al 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2
seg002:A568在var_3中保存策略分类al的值,seg002:A572判断这个策略是否是单体策略(即ah是否小于3)。
接下来的代码就是判断是不是在雨天使用火类策略。
seg002:A580 80 7E FD 00 cmp [bp+var_3], 0 ; 判断是不是火类策略
seg002:A584 75 1D jnz short loc_374C3
seg002:A586 68 6A CF push 0CF6Ah
seg002:A589 9A D8 3F F2 2C call sub_30EF8 ; 获取天气信息 0晴 1雲 2雨
seg002:A58E 3C 02 cmp al, 2 ; 判断是不是雨
seg002:A590 75 11 jnz short loc_374C3
seg002:A592 1E push ds
seg002:A593 68 DE 3B push 3B3Eh ; "雨天不能使用火攻."
下面的是第伍章道具中同样功能的代码,可以看到这个功能的实现方法机会一模一样,而且有一个不易察觉的细节,就是雨天使用火类策略的提示句seg002:A593"雨天不能使用火攻."最后的标点符号是句号,而雨天使用火类道具的提示句seg002:9EF7"雨天不能使用火攻!"最后的标点符号是感叹号。
seg002:9EE6 0A C0 or al, al ; 判断是不是火类道具
seg002:9EE8 75 13 jnz short loc_36E1D
seg002:9EEA 68 6A CF push 0CF6Ah
seg002:9EED 9A D8 3F F2 2C call sub_30EF8 ; 获取天气信息 0晴 1雲 2雨
seg002:9EF2 3C 02 cmp al, 2 ; 判断是不是雨
seg002:9EF4 75 07 jnz short loc_36E1D
seg002:9EF6 1E push ds
seg002:9EF7 68 30 3B push 3B30h ; "雨天不能使用火攻!"
接着先跳过一些代码,当使用策略选择好一个部队后,seg002:A5D4会将部队代码保存在var_2中,然后seg002:A5D7-A607判断是不是一个可以攻击的部队。
seg002:A5D4 88 46 FE mov [bp+var_2], al
seg002:A5D7 3C FF cmp al, 0FFh
seg002:A5D9 74 30 jz short loc_3752B
seg002:A5DB B0 0E mov al, 0Eh
seg002:A5DD F6 66 FE mul [bp+var_2]
seg002:A5E0 05 76 D0 add ax, 0D076h
seg002:A5E3 89 46 EC mov [bp+var_14], ax
seg002:A5E6 50 push ax
seg002:A5E7 9A 9C 40 F2 2C call sub_30FBC ; 获取部队横纵坐标偏移地址
seg002:A5EC 8B D8 mov bx, ax
seg002:A5EE 8B 07 mov ax, [bx]
seg002:A5F0 89 46 F2 mov [bp+var_E], ax
seg002:A5F3 8D 5E F2 lea bx, [bp+var_E]
seg002:A5F6 9A B2 AF F2 2C call sub_37ED2 ; 获取部队地形代码
seg002:A5FB 8A D0 mov dl, al
seg002:A5FD 8A 46 FD mov al, [bp+var_3]
seg002:A600 32 DB xor bl, bl
seg002:A602 9A 84 95 F2 2C call sub_364A4 ; 判断目标部队是否可以被策略攻击
seg002:A607 0B C0 or ax, ax
同样还是对比道具使用中的类似代码。
seg002:9F2A 88 46 FE mov [bp+var_2], al
seg002:9F2D 3C FF cmp al, 0FFh
seg002:9F2F 75 03 jnz short loc_36E54
seg002:9F31 E9 69 05 jmp loc_373BD
seg002:9F34 loc_36E54:
seg002:9F34 B0 0E mov al, 0Eh
seg002:9F36 F6 66 FE mul [bp+var_2]
seg002:9F39 05 76 D0 add ax, 0D076h
seg002:9F3C 89 46 E0 mov [bp+var_20], ax
seg002:9F3F 50 push ax
seg002:9F40 9A F6 40 F2 2C call sub_31016 ; 判断属于我军1还是敌军0
seg002:9F45 56 push si
seg002:9F46 8B F8 mov di, ax
seg002:9F48 9A F6 40 F2 2C call sub_31016 ; 判断属于我军1还是敌军0
seg002:9F4D 3B F8 cmp di, ax
seg002:9F4F 74 2B jz short loc_36E9C
seg002:9F51 8B 46 E0 mov ax, [bp+var_20]
seg002:9F54 89 46 FA mov word ptr [bp+var_6], ax
seg002:9F57 50 push ax
seg002:9F58 9A 9C 40 F2 2C call sub_30FBC ; 获取部队横纵坐标偏移地址
seg002:9F5D 8B D8 mov bx, ax
seg002:9F5F 8B 07 mov ax, [bx]
seg002:9F61 89 46 F8 mov word ptr [bp+var_8], ax
seg002:9F64 8D 5E F8 lea bx, [bp+var_8]
seg002:9F67 9A B2 AF F2 2C call sub_37ED2 ; 获取部队地形代码
seg002:9F6C 8A D0 mov dl, al
seg002:9F6E 8A 46 FF mov al, [bp+var_1]
seg002:9F71 32 DB xor bl, bl
seg002:9F73 9A 84 95 F2 2C call sub_364A4 ; 判断目标部队是否可以被道具攻击
seg002:9F78 0B C0 or ax, ax
[ 本帖最后由 漫漫苦短 于 2026-3-31 20:31 编辑 ]
作者:
漫漫苦短 时间: 2026-4-9 19:19 标题: 二、火水石类策略的使用(2)
本来这节讲策略伤害的具体计算,但最近看到一个现象,龙吟前辈之前的行动价值部分的有关攻击系策略的行动价值公式分析错误,而孝直前辈早在2012年就已经修正了这个错误,但这个错误的修正似乎并没有太大影响力以至于像草原月亮前辈这样的顶尖练级高手仍然把错误的公式运用到布阵走位中,但遇到一些解释不了的问题就只能将异常的行动价值归结于仇人之类的问题。好了,这节的核心内容还是通过其中行动价值分析错误的部分,解释龙吟前辈出错的原因,以及提出个人的一个想法。
【基本策略杀伤表】
焦热 200 火龙 600 猛火 1000
漩涡 300 浊流 700 海啸 1100
落石 400 山崩 800 山洪 1200
(7)如果攻击系策略
基本值=策略基本威力+攻击方策略能力-防御方策略能力-100
阿尔法孝直修正的正确的行动价值公式:
基本值=策略基本威力+攻击方策略能力×2-防御方策略能力+200
可以看到其实正确的公式相比于错误的公式从整体来看相差不大,但就具体数值而言差了(攻击方策略能力 + 300),这就会导致最后的行动价值相差18以上,如果用错误的公式推导实际敌军行动,就可能会对敌军实际的行动产生错误的预估。
下面是关于这部分行动价值的核心计算过程的汇编代码,前面的计算的一些结果保存在内存中如下:
var_1是策略的类型,00火,01水,02石;
var_4是前面已经算好的攻击方策略能力;
var_9是策略的指向范围,例如焦热是00,浊流是01,山洪是02。
seg002:C5AB将防御方策略能力的一部分(防御方等级×智力÷50)保存在SI寄存器中,seg002:C5B4再传回给AX寄存器,CX则是防御方智力。
seg002:C5A2 8A 56 F7 mov dl, [bp+var_9]
seg002:C5A5 2A F6 sub dh, dh
seg002:C5A7 42 inc dx
seg002:C5A8 C1 E2 02 shl dx, 2 ; dx=4(小)8(中)12(大)
seg002:C5AB 8B F0 mov si, ax
seg002:C5AD 8A 46 FF mov al, [bp+var_1] ; al=0(火)1(水)2(石)
seg002:C5B0 2A E4 sub ah, ah
seg002:C5B2 03 D0 add dx, ax ; 4焦热 8火龙 12猛火 5漩涡 9浊流 13海啸 6落石 10山崩 14山洪
seg002:C5B4 8B C6 mov ax, si
seg002:C5B6 6B F2 32 imul si, dx, 50
seg002:C5B9 03 76 FC add si, [bp+var_4] ; +攻击方策略能力
seg002:C5BC 03 F6 add si, si
seg002:C5BE 2B F0 sub si, ax ; 策略基本威力+攻击方策略能力×2+200-防御方等级×智力÷50
seg002:C5C0 2A ED sub ch, ch
seg002:C5C2 2B F1 sub si, cx ; 策略基本威力+攻击方策略能力*2+200-防御方策略能力
seg002:C5B6这步会算出一个与策略有关的数值保存在SI寄存器中,设这个值为x,但是与上面龙吟前辈的策略基本威力有些不一样。
焦热 200 火龙 400 猛火 600
漩涡 250 浊流 450 海啸 650
落石 300 山崩 500 山洪 700
但是seg002:C5BC在将攻击方策略能力翻倍的同时也将x翻倍,设策略基本威力为y,这样立即就能看出两者对应公式为y=2x-200。
而我认为龙吟前辈就是在其中的代码分析中错误的最大原因漏看了seg002:C5BC这行代码,虽然得出了错误的公式并不是单纯是没看到这行的原因,因为上述x和y的对应关系也错了,而行动价值的错误在游戏中并不是很明显在游戏中就能体现出来,因此这个错误即使被纠正了也没有太多玩家知道。
我的分析写作中并不是像很多游戏分析前辈一样只是把最后的分析结果全部罗列出来,而是在其中结合和其他前辈的分析内容并且在其中结合自己的分析内容,并且用其中大量的汇编代码,并入自己的注释,甚至有的时候夹杂了自己的一些想法。在其中放入大类汇编代码其实大部分人也看不太懂,并且就算注释再详细也无法真正教会一个理解不了汇编代码的人,但是我还是想尝试一样这个方式,其实还有另一个目的,就是把分析的汇编代码依据写出来,这样如果在其中有分析错误的汇编代码,像周瑜、孝直前辈就能立刻看出龙吟前辈在其中分析错误,而不是让这样的错误去误导想计算行动价值并运用到布阵走位的极限练级玩家了。
[ 本帖最后由 漫漫苦短 于 2026-4-9 20:49 编辑 ]
作者:
漫漫苦短 时间: 2026-5-9 19:19 标题: 三、火水石类策略的使用(3)
接下来几节的主要内容是关于伤害的计算,关于第一节通过分析得出的var_3和var_7的值在这一节就派上用场了。
和道具的使用类似,首先都要通过一个函数sub_3AA64,其实这个函数,总的来说这是个结算系统,这个结算系统后续的一章会专门来介绍,关于这个结算系统的整体框架分析,目前没有看到相关资料。
策略:
seg002:A630 8A 44 02 mov al, [si+2]
seg002:A633 50 push ax
seg002:A634 8A 46 FE mov al, [bp+var_2]
seg002:A637 50 push ax
seg002:A638 6A 02 push 2
seg002:A63A 8A 46 FD mov al, [bp+var_3] ; 火水石策略的类型
seg002:A63D C0 E0 04 shl al, 4
seg002:A640 0A 46 F9 or al, [bp+var_7] ; 火水石策略的指向范围
seg002:A643 88 46 EA mov [bp+var_16], al
seg002:A646 50 push ax
seg002:A647 68 02 D3 push 0D302h
seg002:A64A 9A 44 DB F2 2C call sub_3AA64
道具:
seg002:9F9C 8A 44 02 mov al, [si+2]
seg002:9F9F 50 push ax
seg002:9FA0 FF 76 FA push word ptr [bp+var_6]
seg002:9FA3 9A 9A AE F2 2C call sub_37DBA
seg002:9FA8 50 push ax
seg002:9FA9 6A 03 push 3
seg002:9FAB 8A 46 FF mov al, [bp+var_1] ; 火水石类道具的类型
seg002:9FAE C0 E0 04 shl al, 4
seg002:9FB1 0A 46 FD or al, [bp+var_3] ; 火水石类道具的指向范围
seg002:9FB4 50 push ax
seg002:9FB5 68 02 D3 push 0D302h
seg002:9FB8 9A 44 DB F2 2C call sub_3AA64
seg002:9FBD E9 DF FE jmp loc_36DBF
要调用sub_3AA64函数,需要传入5个值。seg002:9F9F与seg002:A633传入的值,对应sub_3AA64的arg_8,也就是行动方的战场代码;seg002:9FA8与seg002:A637传入的值,对应sub_3AA64的arg_6,也就是目标方的战场代码,seg002:9FA9与seg002:A638不同,策略是2,道具是3;seg002:9FB4与seg002:A646传入的值,对应sub_3AA644的arg_2,就是根据var_1和var_3的值的计算结果。
设策略的类型即var_1为x,策略指向范围的即var_3为y,最终传入arg_2的值为z,可以得出公式 z = 16x + y。
也就是说焦热的计算结果为0,海啸的计算结果为0x12(18),山崩的计算结果为0x21(33)。这个结果与策略基本威力目前还看不到什么相关联的地方。
焦热 200 火龙 600 猛火 1000
漩涡 300 浊流 700 海啸 1100
落石 400 山崩 800 山洪 1200
然后是sub_3AA64的开头部分,可以看到arg_2值保存在si+0B中,可以看到arg_4值保存在si+0A中。
seg002:DB44 sub_3AA64 proc far
seg002:DB44
seg002:DB44 arg_0 = word ptr 6
seg002:DB44 arg_2 = byte ptr 8
seg002:DB44 arg_4 = byte ptr 0Ah
seg002:DB44 arg_6= byte ptr 0Ch
seg002:DB44 arg_8= byte ptr 0Eh
seg002:DB44
seg002:DB44 C8 1A 00 00 enter 1Ah, 0
seg002:DB48 57 push di
seg002:DB49 56 push si
seg002:DB4A 8B 76 06 mov si, [bp+arg_0]
seg002:DB4D 8A 46 0A mov al, [bp+arg_4]
seg002:DB50 88 44 0A mov [si+0Ah], al
seg002:DB53 8A 46 08 mov al, [bp+arg_2]
seg002:DB56 88 44 0B mov [si+0Bh], al
接下来的代码是策略伤害的行动方策略命中和目标方策略闪避的计算。这里的sub_23A3A函数和sub_294F0函数都已经在第肆章介绍过了,这里有个比较奇怪的地方就是智力算了两次,并且结果都是一样的,不知道为啥在转换成汇编代码时出现了重复。最终行动方策略命中的结果保存在var_6,目标方策略闪避的结果保存在var_2。
行动方:
seg002:D2B9 8A 5C 08 mov bl, [si+8]
seg002:D2BC 2A FF sub bh, bh
seg002:D2BE 03 DB add bx, bx
seg002:D2C0 FF 70 04 push word ptr [bx+si+4]
seg002:D2C3 8B FB mov di, bx
seg002:D2C5 9A DA 6A F6 1C call sub_23A3A ; 获取行动方的等级
seg002:D2CA 03 FE add di, si
seg002:D2CC FF 75 04 push word ptr [di+4]
seg002:D2CF 89 46 EC mov [bp+var_14], ax
seg002:D2D2 9A 90 C5 F6 1C call sub_294F0 ; 获取行动方的智力
seg002:D2D7 FF 75 04 push word ptr [di+4]
seg002:D2DA 89 46 EA mov [bp+var_16], ax
seg002:D2DD 9A 90 C5 F6 1C call sub_294F0 ; 获取行动方的智力
seg002:D2E2 2A E4 sub ah, ah
seg002:D2E4 8B C8 mov cx, ax
seg002:D2E6 8A 46 EC mov al, byte ptr [bp+var_14]
seg002:D2E9 F6 66 EA mul byte ptr [bp+var_16]
seg002:D2EC BA 64 00 mov dx, 100
seg002:D2EF 8B DA mov bx, dx
seg002:D2F1 2B D2 sub dx, dx
seg002:D2F3 F7 F3 div bx
seg002:D2F5 03 C8 add cx, ax ; 等级*智力÷100+智力
seg002:D2F7 89 4E FA mov word ptr [bp+var_6], cx
目标方:
seg002:D2FA 8A 5C 09 mov bl, [si+9]
seg002:D2FD 03 DB add bx, bx
seg002:D2FF FF 70 04 push word ptr [bx+si+4]
seg002:D302 8B FB mov di, bx
seg002:D304 9A DA 6A F6 1C call sub_23A3A ; 获取目标方的等级
seg002:D309 03 FE add di, si
seg002:D30B FF 75 04 push word ptr [di+4]
seg002:D30E 89 46 E8 mov [bp+var_18], ax
seg002:D311 9A 90 C5 F6 1C call sub_294F0 ; 获取目标方的智力
seg002:D316 FF 75 04 push word ptr [di+4]
seg002:D319 89 46 E6 mov [bp+var_1A], ax
seg002:D31C 9A 90 C5 F6 1C call sub_294F0 ; 获取目标方的智力
seg002:D321 2A E4 sub ah, ah
seg002:D323 8B C8 mov cx, ax
seg002:D325 8A 46 E8 mov al, byte ptr [bp+var_18]
seg002:D328 F6 66 E6 mul byte ptr [bp+var_1A]
seg002:D32B BA 64 00 mov dx, 100
seg002:D32E 8B DA mov bx, dx
seg002:D330 2B D2 sub dx, dx
seg002:D332 F7 F3 div bx
seg002:D334 03 C8 add cx, ax ; 等级*智力÷100+智力
seg002:D336 C1 E9 02 shr cx, 2 ; (等级*智力÷100+智力)/4
seg002:D339 89 4E FE mov word ptr [bp+var_2], cx
对比龙吟前辈的分析,第五步的内容基本的一致的,但目前只是计算了策略闪避、策略命中,没有进行比较,而且如果目标方是文官(军乐队/运输队/妖术师),策略闪避要×2,后续会介绍这个比较。
三、策略攻击全分析
策略攻击指使用焦热系策略、漩涡系策略、落石系策略对敌人进行攻击
1.攻击伤害
5)第五步
计算策略闪避
策略闪避=(智力×等级÷100+智力)÷4
计算策略命中
策略命中是一个随机整数,该值大于等于0,小于(智力×等级÷100+智力)
[ 本帖最后由 漫漫苦短 于 2026-5-9 21:09 编辑 ]
| 欢迎光临 轩辕春秋文化论坛 (http://www.xycq.org.cn/forum/) |
Powered by Discuz! 5.0.0 |