三国志9内政系统(转载),运筹帷幄,游戏人生,轩辕春秋文化论坛">


标题: 三国志9内政系统(转载)
性别:未知-离线 永远的小兵

白衣伯爵谏议大夫

Rank: 13Rank: 13Rank: 13Rank: 13
组别 白衣卿相
级别 镇北将军
好贴 1
功绩 185
帖子 3475
编号 1979
注册 2004-4-27


发表于 2004-10-30 08:48 资料 主页 文集 短消息 只看该作者
三国志9内政系统之一:收益<==>金钱篇

作者:三国十

--------------------------------------------------------------------------------

三国9的内政系统,总的说来还算合理吧(我不怎么玩游戏,说得不对不要扔鸡蛋过来  ),本帖无意就此展开评论,只想定量地介绍一下收益与金钱的关系。(在继续阅读之前,假定你还有那么一点点的数学知识)。

首先,根据经验,基本上城市的收益越高,金钱收入也就越多;另外,城市的人口越多,金钱收入似乎也越多,因此可以认为城市的金钱收入是城市收益和城市人口(非兵役人口+兵役人口)的二元函数,可记为
金钱收入=f(城市收益,城市人口)
要考察这个函数关系有很多办法,其中之一就是数字试验。即使用游戏自带的修改功能分别改变收益和人口然后观察金钱收入的变化,最后数据拟合。然而,本帖的方法是从游戏程序汇编源代码入手,解读出其间的定量关系。

由于函数中有两个变量,不便同时考察,可以一个一个地进行。

一、金钱收入与城市收益的关系
首先假定人口是一个常量,那么金钱收入就变成收益的一个一元函数。用数据修改做过试验的朋友应该会发现,这个函数并不是单调递增的。关于这一点,翻看了一下精华区的帖子,首屠执行官已经提到过,当收益超过1300时金钱收入变成收益的减函数。他说的是s9普通版,我不知道普通版的具体极点,然而在PK1.01下,这个准确的数字是1250。也就是说,当收益<=1250时,金钱收入是收益的增函数;而当收益>1250时,金钱收入是收益的减函数。而且,做过数字试验的朋友应该会发现,这个函数还有两个零点:0和2500(意思就是:收益为0或2500时,金钱收入为0)。根据上面这些信息,很容易地想象出这个函数的图象。进一步猜测:这是一个二次函数,而且函数表达式应该是:
金钱收入=A*收益*(2500-收益)
再从汇编代码的角度来考察金钱收入与城市收益的关系(汇编代码及其详细注释见三)。将汇编代码翻译最原始的计算公式:
金钱收入=B*f1(收益)*f2(收益)
其中,
B=f(人口)
f1(收益)=0x10624DD3*(收益*3/2)/(2^32)/(2^6)
f2(收益)=0x68BD8BAD*(2500-收益)/(2^32)/(2^10)
或者合起来写成一大串
金钱收入=f(人口)*0x10624DD3*(收益*3/2)/(2^32)/64*0x68BD8BAD*(2500-收益)/(2^32)/(2^10)
把一些常数进行简记处理后就变成:
金钱收入=f(人口)*C*收益*(2500-收益)
这与前面猜测的公式是相符合的,这就是金钱收入与人口、收益的关系。

二、金钱收入与人口的关系
前面已经考察出人口固定的情况下,金钱收入是收益的二次函数,而且极点是1250。然而及钱收入人口的关系却不是那么直接。我没有做数字试验,因此不知道用数字试验绘制出来的金钱收入~人口的关系曲线是怎么样的。仅从汇编代码来查看,很难看出这个函数关系。
根据汇编代码逻辑,前面的人口因子基数B可以写成
B=f(人口)=g(人口)+0x258
关于g(人口)的计算,大概分成2步:
1. 计算出与(人口^1/2*2)这个数最接近而且是2的幂次的整数,记为c,这一步可以近似地认为是取人口数算数平方根的2倍;
2. 进行以下迭代:
1) t = c;
2) k = [人口数/c];
3) m = 人口数 mod c;
4) c = (k + t - m) / 2;
5) 若c < t则转1),否则迭代结束。
难就难在不知道这段迭代到底是什么含意,那位数值分析学得好的朋友来看看这个迭代是什么运算,若能看出,便可知道那个人口基数因子B与人口的函数关系式。关于金钱收入与人口的关系,其实只需要记住:人口越多越好。

三、计算金钱收入的汇编代码
s9PK1.01中计算金钱收入的汇编代码在0x43A5C0处,下面列出这些代码及其注释。前面的公式其实就是从这些代码翻译过来的。

; 43A5C0: 计算金钱收入的函数入口
; 函数原型:
; int CalcCityMoney( int );
; 入口参数:
; ecx:指向城市数据块的指针

43A5C0 push esi
43A5C1 mov esi, ecx
43A5C3 mov eax, dword ptr [esi]
43A5C5 push edi
43A5C6 call [eax + 0DCh]
; 上面的这个call指令调用一个子例程,那个子例程将城市兵役人口与非兵役人口相加以
; 得到城市人口数,并将人口数存于寄存器eax中返回
43A5CC push eax
43A5CD call [5FF31C]
;上面这个call指令实际上调用了SanCalc.dll中的一个计算函数(s9PK中涉及计算的代码几乎都在
; SanCalc.dll中)。该函数计算出一个人口因子基数,大概分两步计算,见二中的描述。这里不
; 再列出SanCalc.dll中的这个计算函数的汇编代码,有兴趣的朋友自己去查看。
43A5D3 mov edx, [esi]
43A5D5 mov edi, eax
43A5D7 add esp, 4
43A5DA mov ecx, esi
43A5DC add edi, 258h
43A5E2 call [edx + 0F0h]
; 上面的这个call指令调用一个子例程,该子例程读取城市收益,并存于eax中返回

;
; 下面的代码(从43A5E8到43A605)便是前面公式中f1(收益)函数的体现
;
43A5E8 imul edi, eax
; edi <= 人口因子基数*收益
43A5EB lea ecx, [edi * 2 + edi]
; ecx <= edi * 3
43A5EE shl ecx, 1
; ecx <= ecx / 2
43A5F0 mov eax, 10624DD3
43A5F5 imul ecx
; eax <= 10624DD3 * ecx
43A5F7 sar edx, 6
43A5FA mov eax, edx
43A5FC shr eax, 1F
43A601 mov edi, edx
; 至此,edi = f1(收益)

;
; 下面的代码(43A603至43A625)完成其余计算,此处从略。
;

四、如何修改
很多朋友关心的可能是如何修改商业上限、改动上限后如何使金钱不减少以及如何使较少的收益能够带来较多的金钱收入等问题。
1、如何改收益上限
默认情况下,收益上限<=1000。事实上,每个城市都有它的收益上限,可以在内存中修改。以西平为例,收益上限位于地址0x12F01FC处。比如要将西平的收益上限改为5000,那么可以在0x12F01FC处写入该数值(注意little endian)。其他城市怎么办?fpe大法……
2、如何改金钱收入的极值点
看了前面的公式,应该很容易明白,金钱收入~收益函数关系的极值点在收益=1250处。要改变这个极值点,只需要改动那个2500即可。这个数值在内存中位于0x43A60E处。找到这里,比如要想将极值点设成3000,那么就需要在0x43A60E那儿填入6000的数值(注意little endian)。
3、如何改变金钱收入~收益关系
其实2中的修改也会附带带来金钱收入~收益关系的修改。其实要想以较少的收益获得较高的金钱收入,改法有很多,自己回去查看前面的汇编代码,然后想想怎么改(举个例子,比如那些右移6的地方,让它少移一点,就可以增加)。


顶部
性别:未知-离线 永远的小兵

白衣伯爵谏议大夫

Rank: 13Rank: 13Rank: 13Rank: 13
组别 白衣卿相
级别 镇北将军
好贴 1
功绩 185
帖子 3475
编号 1979
注册 2004-4-27


发表于 2004-10-30 08:50 资料 主页 文集 短消息 只看该作者
三国志9内政系统之二:粮食<==>收获篇

作者:三国十

--------------------------------------------------------------------------------

前面的帖子介绍了城市金钱收入的计算公式,据此可以大胆地猜测:粮食收入的计算公式应该与此类似。事实中正是如此,除一些常数项的不同外,二者的计算方法完全一致,因此这里就直接列出公式,而不去探究该公式的来源了。

一、城市粮食收入的计算公式
(这里以自变量x1代表收或,自变量x2代表城市人口,以因变量y代表粮食收入)
y = B * f1(x1) * f2(x1)
其中
B = f(x2) + 0x12C
关于f(x2)的计算方法与前面帖子中介绍的方法相同。
f1(x1) = 0x66666667 * x1 / (2^32) / 4;
f2(x1) = 0x10624DD3 * (4000 - x1) / (2^32) / (2^8);
合起来写就是
y = [f(x2) + 0x12C] * [0x66666667 * x1 / (2^32) / 4] *[ 0x10624DD3 * (4000-x1) / (2^32) / (2^8)]
将一些常数项作简记处理,得到
y = [f(x2) + 0x12C] * C * x1 * (4000 - x1)
当人口x2固定时,粮食收入是收获的二次函数,该函数在x1 = 2000时取得极大值。

二、有关收获、粮食收入的修改
1、收获上限
其实要修改城市的收获上限,最简单的方法是用存档修改器或者剧本修改器。若要直接修改内存,也是可以的,以西平为例,收获位于0x12501F8,收获上限位于0x1250200。

2、粮食收入的极值点
粮食收入的极值点是当收获为2000时。如要移动,比如要将此极值点变为4000,那么就把内存0x43A689处的那个4000改成8000。


顶部
性别:未知-离线 永远的小兵

白衣伯爵谏议大夫

Rank: 13Rank: 13Rank: 13Rank: 13
组别 白衣卿相
级别 镇北将军
好贴 1
功绩 185
帖子 3475
编号 1979
注册 2004-4-27


发表于 2004-10-30 08:53 资料 主页 文集 短消息 只看该作者
三国志9内政系统之补充:人口因素

作者:三国十

前面两个帖子中曾提到,人口作为一个因素参与到金钱收入和粮食收入的计算当中,但当时并没有得到金钱或粮食收入与人口的函数关系。下午做了一些试验,发现其实就是平方根的关系。即前面的f(人口)就是:
f(人口)=sqrt(人口)
由此也可看出,S9的程序代码为了保持跨平台的兼容性,竟然将这种简单的浮点运算通过迭代来算法来实现,而没有专门针对具体平台采用浮点指令进行优化计算,这对于计算速度还是有一定影响的.
顶部
性别:男-离线 飞将军吕布

Rank: 4
组别 士兵
级别 护军
功绩 5
帖子 443
编号 19285
注册 2004-10-21


发表于 2004-10-30 09:14 资料 主页 短消息 只看该作者
晕,好难,看不懂
顶部
性别:男-离线 龙鹰凌渡宇

Rank: 7Rank: 7Rank: 7Rank: 7
组别 校尉
级别 后将军
功绩 15
帖子 1443
编号 19944
注册 2004-10-30


发表于 2004-10-30 09:48 资料 主页 文集 短消息 只看该作者
好贴。。
不过怎麽也想不出费劲修改钱粮上限有何用?前期内政不满,后期钱粮无限。
顶部
性别:未知-离线 elz5000

Rank: 5Rank: 5
组别 士兵
级别 安国将军
功绩 8
帖子 819
编号 4570
注册 2004-1-17


发表于 2004-10-30 12:29 资料 短消息 只看该作者
对bt地图有用
顶部
性别:未知-离线 天下有敌

Rank: 2Rank: 2
组别 百姓
级别 奋威校尉
功绩 1
帖子 118
编号 6963
注册 2004-4-21


发表于 2004-11-2 00:33 资料 短消息 只看该作者
太阳啊,专业人士上场,果然厉害啊
顶部

正在浏览此帖的会员 - 1 人在线 - 0 位会员(0 隐身), 1 位游客




当前时区 GMT+8, 现在时间是 2025-2-6 23:26
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.012655 second(s), 8 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP