2025-2-22 19:19
漫漫苦短
DOS版三国志英杰传的研究心得——叁
想必大家都曾经看过下面的分析,说实话迫切地想弄清楚下面内容在代码中的具体细节也是我当初想进行反汇编研究的研究方向之一,这一章内容就是在龙吟前辈在写出下面分析之后,时隔20余年之后再次让它们展示出来。
[quote]偏移+00 占2字节 人物代码(刘备=0000,关羽=0001)
偏移+02 占1字节 战场代码(00=我军第1只部队、0E=我军第15只部队,0F=敌军第1只部队)
(注:00-0E是我军,共15个位置,但不一定用完,0F-2C是敌军,共30个位置,但不一定用完)
偏移+03 占1字节 部队横坐标(以左上角为0,0)
偏移+04 占1字节 部队纵坐标
偏移+05 占1字节 仇人代码(FF表示没有仇人)
偏移+06 占2字节 目标横纵坐标(0000表示没有目标)
偏移+08 占1字节 不明
偏移+09 占1字节 部队撤退标志(00=消失 01=未出场 02=正常 04=撤退)
偏移+0A 占1字节 部队状态(从低位开始:第2位为1表示混乱,第3位为1表示全屏移动,第6位为0表示伏兵,第8位为1表示行动结束)
偏移+0B 占1字节 部队AI类型(见后)
偏移+0C 占1字节 部队士气
偏移+0D 占1字节 部队策略值[/quote]
根据前面的分析,不难看出这也是存储在DS段的一块内存空间,可是龙吟前辈并没有写出这块内存空间的具体地址,还有空间究竟有多大,还有这些偏移以及数据的内容是如何得出的,这章就简单来分析一下这些内容。
2025-2-22 19:19
漫漫苦短
一、战场数据所在位置
这块地址的起始地址是DS: D076,每只在战场上的部队使用14字节的大小,一共45只部队,所以一共是14*45=630字节大小,从DS: D076到DS: D2EB这部分长达0x276大小的空间,存储的都是上面龙吟分析的内容。
接下来我们简要把上述的数据内容进行初步解释,比如说D076, 14, 45这样的数据都是怎么来的。
如何证明是上述的内容保存在D076是不容易的,因为需要花费大量的时间进行研究,而我们可以推测以DS: D076为起始,由此往后的0x276的大小的内存空间被占用,这是目前能分析出来的。
在IDAPro搜索常量(按下Alt+I)0xD076,可以在其中看到Instruction这一列代码中包含D076的代码,出现的比较频繁的语句一条语句是add ax, 0D076h。
[attach]151055[/attach]
[attach]151056[/attach]
我们在Address这一列中找到seg002:774B,点击就会弹到下面代码的位置。
[code]seg002:7742 C6 46 FF 00 mov [bp+var_1], 0 ;var_1=0...2C
seg002:7746 loc_34666: ; CODE XREF: sub_3460C+98↓j
seg002:7746 B0 0E mov al, 0Eh
seg002:7748 F6 66 FF mul [bp+var_1] ; 部队战场代码
seg002:774B 05 76 D0 add ax, 0D076h
...
seg002:777D FE 46 FF inc [bp+var_1]
seg002:7780 80 7E FF 2D cmp [bp+var_1], 2Dh
seg002:7784 72 C0 jb short _for_loc_34666[/code]
从中不难看出这段代码是印证龙吟的部分分析,var_1代表循环的战场代码(0...2Ch)共45个战场代码,而从中的mov al, 0Eh可以看出,每个战场代码需要占用14字节大小的空间,而add ax, 0D076h表示这些数据都是从D076开始的。
seg002:7746 — seg002:774B就是其中计算部队战场数据的首地址的过程,可以列2个16进制的公式:
部队战场数据的首地址 = D076+部队战场代码*E
部队战场数据占用地址 = (D076+部队战场代码*E — D076+部队战场代码*E+D)
根据计算,部队战场代码为0部队占用地址是(D076 — D083 ),部队战场代码为1部队占用地址(D084 — D091 ),部队战场代码为F部队数据的首地址为D148,而部队战场代码为C部队占用地址(D2DE— D2EB ),可能有人会想要扩容其中的数据,但是DS: D075以及前面的地址和DS: D2EC以及后面的地址都保存数据,如果想扩容需要把其中的数据进行“搬移”,而且所需要修改的代码量相当大,并且有可能会有遗漏并且出现BUG。
[color=Silver][[i] 本帖最后由 漫漫苦短 于 2025-2-22 19:49 编辑 [/i]][/color]
2025-2-25 19:19
漫漫苦短
二、战场数据的简单方法(一)
第一节说明了在D076到D2EB之间的14*45字节的内容保存了其中部队在战场上的一些数据,并且通过各自的战场代码可以找到其占用地址以及连续的14字节,而龙吟前辈已经将这14字节对应的含义列举出来了,那么先看看这些数据是怎么被使用的,也就是它们的一些方法。
首先最简单的,就是每一项数据需要拿到(Get)和设置(Set),下列介绍部分数据的这两个方法。
以下未说明,arg_0的值都是以D076为首项,D(14)为公差,2D(45)为项数的一个十六进制下的等差数列中的一个地址值,就是说arg_0的值并不是唯一的,不像前一章介绍的CF6A,它的值可以有变动,但是这些函数的意义都是类似的。
部队人物代码的Get方法,注意一下 mov ax, [bx]和 mov ax, bx的区别,前者是将bx这个地址的保存的数据的值传给ax,后者是将bx的值传给ax。
例如bx为D076,mov ax, [bx]就是将bx地址所在的人物代码传给ax,mov ax, bx就是让ax也变为D076。
[code]seg002:4062 sub_30F82 proc far
seg002:4062 arg_0 = word ptr 6
seg002:4062
seg002:4062 55 push bp
seg002:4063 8B EC mov bp, sp
seg002:4065 8B 5E 06 mov bx, [bp+arg_0]
seg002:4068 8B 07 mov ax, [bx]
seg002:406A C9 leave
seg002:406B CA 02 00 retf 2
seg002:406B sub_30F82 endp[/code]
部队仇人代码的两个方法
[code]
seg002:93A6 sub_362C6 proc far
seg002:93A6 arg_0 = word ptr 6
seg002:93A6
seg002:93A6 55 push bp
seg002:93A7 8B EC mov bp, sp
seg002:93A9 8B 5E 06 mov bx, [bp+arg_0]
seg002:93AC 8A 47 05 mov al, [bx+5]
seg002:93AF C9 leave
seg002:93B0 CA 02 00 retf 2
seg002:93B0 sub_362C6 endp
seg002:93B4 sub_362D4 proc far
seg002:93B4
seg002:93B4 arg_0 = word ptr 6
seg002:93B4 arg_2 = byte ptr 8
seg002:93B4
seg002:93B4 55 push bp
seg002:93B5 8B EC mov bp, sp
seg002:93B7 8B 5E 06 mov bx, [bp+arg_0]
seg002:93BA 8A 46 08 mov al, [bp+arg_2]
seg002:93BD 88 47 05 mov [bx+5], al
seg002:93C0 C9 leave
seg002:93C1 CA 04 00 retf 4
seg002:93C1 sub_362D4 endp
[/code]
部队撤退标志的两个方法
[code]
seg002:40D8 sub_30FF8 proc far
seg002:40D8
seg002:40D8 arg_0 = word ptr 6
seg002:40D8 arg_2 = byte ptr 8
seg002:40D8
seg002:40D8 55 push bp
seg002:40D9 8B EC mov bp, sp
seg002:40DB 8B 5E 06 mov bx, [bp+arg_0]
seg002:40DE 8A 46 08 mov al, [bp+arg_2]
seg002:40E1 88 47 09 mov [bx+9], al
seg002:40E4 C9 leave
seg002:40E5 CA 04 00 retf 4
seg002:40E5 sub_30FF8 endp
seg002:40E8 sub_31008 proc far
seg002:40E8 arg_0 = word ptr 6
seg002:40E8
seg002:40E8 55 push bp
seg002:40E9 8B EC mov bp, sp
seg002:40EB 8B 5E 06 mov bx, [bp+arg_0]
seg002:40EE 8A 47 09 mov al, [bx+9]
seg002:40F1 C9 leave
seg002:40F2 CA 02 00 retf 2
seg002:40F2 sub_31008 endp
[/code]
部队AI类型的两个方法
[code]
seg002:410E sub_3102E proc far
seg002:410E
seg002:410E arg_0 = word ptr 6
seg002:410E
seg002:410E 55 push bp
seg002:410F 8B EC mov bp, sp
seg002:4111 8B 5E 06 mov bx, [bp+arg_0]
seg002:4114 8A 47 0B mov al, [bx+0Bh]
seg002:4117 C9 leave
seg002:4118 CA 02 00 retf 2
seg002:4118 sub_3102E endp
seg002:7C4A sub_34B6A proc far
seg002:7C4A
seg002:7C4A arg_0= word ptr 6
seg002:7C4A arg_2= byte ptr 8 ;部队AI类型
seg002:7C4A
seg002:7C4A 55 push bp
seg002:7C4B 8B EC mov bp, sp
seg002:7C4D 80 7E 08 07 cmp [bp+arg_2], 7
seg002:7C51 77 09 ja short locret_34B7C ;arg_2大于7,是不合法的AI类型,跳出函数
seg002:7C53 8B 5E 06 mov bx, [bp+arg_0]
seg002:7C56 8A 46 08 mov al, [bp+arg_2]
seg002:7C59 88 47 0B mov [bx+0Bh], al
seg002:7C5C
seg002:7C5C locret_34B7C: ; CODE XREF: sub_34B6A+7↑j
seg002:7C5C C9 leave
seg002:7C5D CA 04 00 retf 4
seg002:7C5D sub_34B6A endp
部队策略值一个方法,还有两个方法,一个是计算最大策略值,就是导致94智力值的部队到99级策略值为0的那个,还有一个是补充策略值的方法,这两个方法到时候再介绍。
[code]
seg002:406E sub_30F8E proc far
seg002:406E
seg002:406E arg_0 = word ptr 6
seg002:406E arg_2 = byte ptr 8
seg002:406E
seg002:406E 55 push bp
seg002:406F 8B EC mov bp, sp
seg002:4071 8B 5E 06 mov bx, [bp+arg_0]
seg002:4074 8A 46 08 mov al, [bp+arg_2]
seg002:4077 88 47 0D mov [bx+0Dh], al
seg002:407A C9 leave
seg002:407B CA 04 00 retf 4
seg002:407B sub_30F8E endp
[/code]
很神奇的一点是,我暂时没有找到并没有部队策略值的Get方法,因为在程序的代码中都是直接获取的,并没有单独构造出一个函数,见以下两个例子。
[code]
seg002:8FF2 8B 5E 06 mov bx, [bp+arg_0]
seg002:8FF5 8A 47 0D mov al, [bx+0Dh]
[/code]
[code]
seg002:A4D2 8B 76 06 mov si, [bp+arg_0]
...
seg002:A510 8A 44 0D mov al, [si+0Dh]
[/code]
部队战场坐标的Get方法,准确来说是取一个偏移地址。
[code]
seg002:409C sub_30FBC proc far ; CODE XREF: _InitBattle_sub_2FB7A+25B↑P ...
seg002:409C
seg002:409C arg_0 = word ptr 6
seg002:409C
seg002:409C 55 push bp
seg002:409D 8B EC mov bp, sp
seg002:409F 8B 46 06 mov ax, [bp+arg_0]
seg002:40A2 05 03 00 add ax, 3
seg002:40A5 C9 leave
seg002:40A6 CA 02 00 retf 2
seg002:40A6 sub_30FBC endp
[/code]
然后在函数外获得这个地址保存的具体坐标值数据,见以下两个例子
[code]
seg002:2EB2 68 76 D0 push 0D076h
seg002:2EB5 9A 9C 40 F2 2C call sub_30FBC ; 获取我军主将战场坐标偏移地址
seg002:2EBA 8B D8 mov bx, ax
seg002:2EBC 8B 07 mov ax, [bx]
[/code]
[code]
seg002:3008 B0 0E mov al, 14
seg002:300A F6 66 FF mul [bp+var_1] ; 部队战场代码
seg002:300D 05 76 D0 add ax, 0D076h
seg002:3010 89 46 F8 mov [bp+var_8], ax
seg002:3013 50 push ax
seg002:3014 9A 9C 40 F2 2C call sub_30FBC ; 获取部队横纵坐标偏移地址
seg002:3019 8B D8 mov bx, ax
seg002:301B 8B 07 mov ax, [bx]
[/code]
注意D076地址放的不一定是劉備的数据,虽然这个地址战场代码是0,但是劉備也不是每一战都出,不过劉備出的每一战战场代码都是0。
[color=Silver][[i] 本帖最后由 漫漫苦短 于 2025-3-1 19:19 编辑 [/i]][/color]
2025-3-1 19:19
漫漫苦短
三、战场数据的简单方法(二)
上节讲了人物代码、仇人代码、撤退标志、AI类型、策略值、战场坐标偏移地址的最简单方法,从这些方法是看不出来的它们的含义的,这节介绍的这几个方法,或许能从它们的代码中窥见其中的奥秘。
以下未说明,arg_0的值都是以D076为首项,D(14)为公差,2D(45)为项数的一个十六进制下的等差数列中的一个地址值。
一个是部队的战场代码,就是0-2C中的一个值。
[code]
seg002:AE9A sub_37DBA proc far
seg002:AE9A
seg002:AE9A arg_0 = word ptr 6
seg002:AE9A
seg002:AE9A 55 push bp
seg002:AE9B 8B EC mov bp, sp
seg002:AE9D 8B 5E 06 mov bx, [bp+arg_0]
seg002:AEA0 8A 47 02 mov al, [bx+2]
seg002:AEA3 C9 leave
seg002:AEA4 CA 02 00 retf 2
seg002:AEA4 sub_37DBA endp
[/code]
这时就需要引出关键问题了,游戏是如何是如何根据战场代码判断是这支部队是我方(我军加友军)还是敌方。
[code]
seg002:40F6 sub_31016 proc far
seg002:40F6
seg002:40F6 arg_0 = word ptr 6
seg002:40F6
seg002:40F6 55 push bp
seg002:40F7 8B EC mov bp, sp
seg002:40F9 8B 5E 06 mov bx, [bp+arg_0]
seg002:40FC 80 7F 02 0F cmp byte ptr [bx+2], 0Fh ; 比较部队战场代码与0F
seg002:4100 72 04 jb short loc_31026 ; 无符号小于跳转
seg002:4102 33 C0 xor ax, ax ; 返回0,属于敌军
seg002:4104 EB 03 jmp short locret_31029
seg002:4106 loc_31026: ; CODE XREF: sub_31016+A↑j
seg002:4106 B8 01 00 mov ax, 1 ; 返回1,属于我军
seg002:4109 locret_31029: ; CODE XREF: sub_31016+E↑j
seg002:4109 C9 leave
seg002:410A CA 02 00 retf 2
seg002:410A sub_31016 endp
[/code]
这段就可以简单地印证以上龙吟前辈的结论:
[quote]
(注:00-0E是我军,共15个位置,但不一定用完,0F-2C是敌军,共30个位置,但不一定用完)
[/quote]
但其实还有一个小问题,英杰传存在战场倒戈的情形,有的敌军会变成我军,战场代码到底会不会改变,那么是不是这个函数就不适用了。我们先提出两个设想:
[list=1]
[*]敌军即我军,这些敌军的战场代码一开始就是我军(0-E),只是在敌军回合被操作,某种意义上来说这是个“友军”。
[*]一开始就属于敌军,战场代码一开始是敌军(F-2C),在倒戈后战场代码为我军(0-E)。
[/list]
1的设想与未倒戈敌军的实际情况不符合,未倒戈敌军在敌军中并不特殊,比如说这种敌军获取经验的方式是敌军的方式(只有策略才能获得),如果加上特殊判断就太多余了,不过能印证上我军的包括倒戈的人从来就没有超过15人的缘故,而且使用剧情修改器也无法实现超出15人吧,雒II为啥就只倒戈了吴兰和李严,吴懿雷铜费观不是不想倒戈拿经验,实在是劉備军中位置不够:titter:
2的设想能解决1中未倒戈敌军在敌军中行为正常的情况,但反而不能印证上面的问题了。
实际上,英杰传使用了第3种方式,在2的基础上还有加上一个过程,这里先暂时不叙述,以后还会给出说明的,评论也可以给出一些猜想。
接下来是士气值的2个方法。
获取士气值
[code]
seg002:9398 sub_362B8 proc far
seg002:9398
seg002:9398 arg_0 = word ptr 6
seg002:9398
seg002:9398 55 push bp
seg002:9399 8B EC mov bp, sp
seg002:939B 8B 5E 06 mov bx, [bp+arg_0]
seg002:939E 8A 47 0C mov al, [bx+0Ch]
seg002:93A1 C9 leave
seg002:93A2 CA 02 00 retf 2
seg002:93A2 sub_362B8 endp
[/code]
士气值变动的一部分代码。
[code]
seg002:7B7E sub_34A9E proc far
seg002:7B7E
seg002:7B7E var_1 = byte ptr -1
seg002:7B7E arg_0= word ptr 6
seg002:7B7E arg_2= word ptr 8 ;新士气值
seg002:7B7E
seg002:7B7E C8 02 00 00 enter 2, 0
seg002:7B82 8B 5E 06 mov bx, [bp+arg_0]
seg002:7B85 8B 56 08 mov dx, [bp+arg_2]
seg002:7B88 8A 47 0C mov al, [bx+0Ch]
seg002:7B8B 88 46 FF mov [bp+var_1], al ; var_1保存原士气值
seg002:7B8E 0B D2 or dx, dx ; 判断新士气值是不是小于0
seg002:7B90 7D 06 jge short loc_34AB8 ; 有符号大于等于跳转
seg002:7B92 C6 47 0C 00 mov byte ptr [bx+0Ch], 0 ; 新士气值设为0
seg002:7B96 EB 0E jmp short loc_34AC6
seg002:7B98 loc_34AB8: ; CODE XREF: sub_34A9E+12↑j
seg002:7B98 83 FA 64 cmp dx, 100 ; 判断新士气值是不是大于100
seg002:7B9B 7E 06 jle short loc_34AC3 ; 有符号大于等于跳转
seg002:7B9D C6 47 0C 64 mov byte ptr [bx+0Ch], 100 ; 新士气值设为100
seg002:7BA1 EB 03 jmp short loc_34AC6
seg002:7BA3 loc_34AC3: ; CODE XREF: sub_34A9E+1D↑j
seg002:7BA3 88 57 0C mov [bx+0Ch], dl ; 修改部队战场数据的士气值
seg002:7BA6 loc_34AC6:
seg002:7BA6 8A 46 FF mov al, [bp+var_1]
seg002:7BA9 2A E4 sub ah, ah
seg002:7BAB 3B C2 cmp ax, dx ; 比较原士气值和新士气值
seg002:7BAD 7E 1D jle short loc_34AEC ; 有符号小于等于跳转
seg002:7BAF 83 FA 1E cmp dx, 30 ; 比较新士气值与30
seg002:7BB2 73 2E jnb short locret_34B02 ; 无符号不小于跳转
seg002:7BB7 9A E0 3D F6 1C call sub_20D40 ; 0-4混亂随机数
seg002:7BBC 3C 03 cmp al, 3 ; 比较随机数与3
seg002:7BBE 73 22 jnb short locret_34B02 ; 无符号不小于跳转
... ;隐藏的内容为部队陷入混亂的代码
seg002:7BCA EB 16 jmp short locret_34B02
seg002:7BCC loc_34AEC: ; CODE XREF: sub_34A9E+2F↑j
seg002:7BCC 8A 46 FF mov al, [bp+var_1]
seg002:7BCF 2A E4 sub ah, ah
seg002:7BD1 3B C2 cmp ax, dx ; 比较原士气值和新士气值
seg002:7BD3 7C 05 jl short loc_34AFA ; 有符号小于则跳转
seg002:7BD5 83 FA 64 cmp dx, 100 ; 判断新士气值是不是100
seg002:7BD8 75 08 jnz short locret_34B02
seg002:7BDA loc_34AFA: ; CODE XREF: sub_34A9E+55↑j
... ;隐藏的内容为部队混乱恢复的代码
seg002:7BE2 locret_34B02:
seg002:7BE2 C9 leave
seg002:7BE3 CA 04 00 retf 4
seg002:7BE3 sub_34A9E endp
[/code]
[color=Silver][[i] 本帖最后由 漫漫苦短 于 2025-3-1 19:39 编辑 [/i]][/color]
2025-3-2 19:19
漫漫苦短
四、战场数据的简单方法(三)
接下来介绍的就是要和前章内容有所联动的,如果有看不明白的可以复习一下以前的知识点。
[code]seg002:AFB2 sub_37ED2 proc far
seg002:AFB2 57 push di
seg002:AFB3 56 push si
seg002:AFB4 8B F3 mov si, bx ; bx=部队横纵坐标地址
seg002:AFB6 8A 04 mov al, [si]
seg002:AFB8 38 06 68 CF cmp byte_4D738, al ; 比较地图W与部队横坐标X
seg002:AFBC 76 2C jbe short loc_37F0A ; 无符号小于等于跳转
seg002:AFBE A0 69 CF mov al, byte_4D739
seg002:AFC1 38 44 01 cmp [si+1], al ; 比较部队纵坐标Y与地图H
seg002:AFC4 73 24 jnb short loc_37F0A ; 无符号不小于跳转
seg002:AFC6 68 08 55 push 5508h
seg002:AFC9 9A 08 1D F6 1C call sub_1EC68
seg002:AFCE 5B pop bx
seg002:AFCF 8E C2 mov es, dx
seg002:AFD1 8B D8 mov bx, ax
seg002:AFD3 8A 04 mov al, [si] ; X
seg002:AFD5 2A E4 sub ah, ah
seg002:AFD7 03 D8 add bx, ax
seg002:AFD9 80 C7 0F add bh, 0Fh
seg002:AFDC 8A 44 01 mov al, [si+1] ; Y
seg002:AFDF F6 26 68 CF mul byte_4D738
seg002:AFE3 8B F8 mov di, ax ; di=W*Y
seg002:AFE5 26 8A 01 mov al, es:[bx+di] ; 部队地形代码 es{5508}:[W*Y+X+0F00h]
seg002:AFE8 EB 02 jmp short loc_37F0C
seg002:AFEA loc_37F0A: ; CODE XREF: sub_37ED2+A↑j sub_37ED2+12↑j
seg002:AFEA B0 FF mov al, 0FFh
seg002:AFEC
seg002:AFEC loc_37F0C: ; CODE XREF: sub_37ED2+36↑j
seg002:AFEC 5E pop si
seg002:AFED 5F pop di
seg002:AFEE CB retf
seg002:AFEE sub_37ED2 endp[/code]
byte_4D738和byte_4D739就是用到了[url=http://xycq.org.cn/forum/viewthread.php?tid=310127#pid4097626]第二章的内容[/url]
总体来进行分析吧,seg002:AFB4到seg002:AFC4中是这个函数的第一部分,这部分内容就是看传入bx这个部队横纵坐标地址的数据是否合法,就是说横纵坐标不能大于这个地图的W和H。
如果数据合法就执行第二部分seg002:AFC6到seg002:AFE8,这部分注意seg002:AFD9 add bh, 0Fh,bh加0Fh,但后面是+0F00h,就像是一个十进制两位数AB,给A加1,新的数实际上是加10,而单字节寄存器BH和BL构成双字节寄存器BX,BH加1,BX就增加100h。最后AL返回对应的地形代码。
而数据不合法,执行第三部分seg002:AFEA这一行,AL返回FF。
有了这个函数的基础,还可以介绍下面这个函数。
[code]seg002:AEEA sub_37E0A proc far
seg002:AEEA 9A B2 AF F2 2C call sub_37ED2
seg002:AEEF 3C 08 cmp al, 8 ; 08村莊
seg002:AEF1 74 0C jz short loc_37E1F
seg002:AEF3 3C 0D cmp al, 0Dh ; 0D鹿砦
seg002:AEF5 74 08 jz short loc_37E1F
seg002:AEF7 3C 0E cmp al, 0Eh ; 0E兵營
seg002:AEF9 74 04 jz short loc_37E1F
seg002:AEFB 33 C0 xor ax, ax
seg002:AEFD EB 03 jmp short locret_37E22
seg002:AEFF loc_37E1F:
seg002:AEFF B8 01 00 mov ax, 1
seg002:AF02
seg002:AF02 locret_37E22: ; CODE XREF: sub_37E0A+13↑j
seg002:AF02 CB retf
seg002:AF02 sub_37E0A endp[/code]
seg002:AEEA这句先横纵坐标地址获取对应的地形代码。seg002:AEEF到seg002:AEF9依次判断这个地形代码是不是08村莊0D鹿砦0E兵營,如果是其中一个就跳到seg002:AEFF这行执行返回1,而都不是就不跳转seg002:AEFB这行执行返回0。
这里有个疑问,是部分把对应的地形代码修改,就能实现在不同的地形实现回合初兵力和士气值的自动恢复。其一,不仅仅可以修改这其中的地形代码,还能修改三个jz的比较,可以修改为jnz, ja, jb, jbe, jnb等等,这样就有可能实现不仅仅识别三个地形,可以识别一个区间的地形加上另一个地形,或者一个区间中减去其中一个地形,这样就能实现更丰富的修改;其二就是泼个冷水了,这个函数很明显没有区分村莊鹿砦恢复兵力和士气值而兵營只回复兵力的实际情况,因为这三种地形都是返回1,如果真的仅仅改了这部分,那么只会敌军的行为发生改变。
实际上,这个函数的判断被两个部分的函数使用,一是前辈们总结的敌军和友军的行动顺序中的第一行动梯队——村莊鹿砦兵營中的部队,那部分需要这个函数的判断部队是否在村莊鹿砦兵營,二是龙吟的分析结果中会在行动价值额外加50中判断地图中是否有可恢复地形,用这个函数判断这些某一个坐标是否满足其中的条件。
所以如果仅仅修改这个函数,有可能只是让敌军扎堆在某个地形,而对应地形没有回复的话,部队只是会提前行动而不会离开这个地形等等情况。
[color=Silver][[i] 本帖最后由 漫漫苦短 于 2025-3-2 19:48 编辑 [/i]][/color]
页:
[1]
Powered by Discuz! Archiver 5.0.0
© 2001-2006 Comsenz Inc.