关于UN:U命令产生BUG的研究
关于UN:U命令产生BUG的研究首先,这个BUG也许好早就有人发现.不过我是今天才认识到的,和大家分享一下研究心得.
事情起于对当年一幅WOG化出错地图的研究.
地图的名字是<Arena of death>,里面拥有很多宝箱和各种资源.当年玩时按照一般惯例不开启<替换物体>选项,但WOG化后仍然出错,由于当时不太懂ERM语法.但那句cannot find more objects 一直很深刻.出错后如果继续玩,后期会有意想不到的现象,比如特长兵种的,攻防都固定为400几以上了.
最近找到了那张地图重玩,问题依旧.此时已经比较容易找到出错的位置,是选项<一些箱子会有更多的钱>的问题,禁用了就没出错信息.
该选项对应的ERM是script00.erm中的以下语句:
** upgrade chests
!!UN:P132/?y3; 检测选项是否开启
!!UN&y3=1:U101/-1/?v951;
!!VRv952:S-1;
!!DO679/1/v951/1&y3=1:P; 始循环所有宝箱,并使箱子有机会获得更多钱
** function to possibly upgrade a treasure chest
!?FU679; [使箱子获得更多钱的函数]
!!UN:U101/-1/-1/952; 出错在此句上
!!VRy1:S0 R99;
!!CH952&y1<8:B5;
!!CH952&y1>97:B6;
** end of function
乍看句子都很正常,为什么会出错呢?联想起cannot find more objects,估计是因为没有找到对应的物体(宝箱).
于是加入了在两段中加入几句来看看到底什么时候出错.
!!UN:P132/?y3;
!!UN&y3=1:U101/-1/?v951;
!!VRv952:S-1;
!!VRv9999:S0; [增加]
!!IF:M^宝箱总数 %V951^; [增加]
!!DO679/1/v951/1&y3=1:P;
** function to possibly upgrade a treasure chest
!?FU679;
!!VRv9999:+1; [增加]
!!UN:U101/-1/-1/952;
!!VRy1:S0 R99;
!!CH952&y1<8:B5;
!!CH952&y1>97:B6;
** end of function重新WOG化出错后,查看WOGERMLOG.TXT文件(记录变量信息文件).
发现V9999刚好循环到最后一个(V951)时出错.(V9999=V951)
再看看出错前一个宝箱的坐标v952-v954,翻看地图,俨然是最后一个的箱子了(地下层的最右下的该物体).
为了再验证是最后一个循环出错,减少了地图的宝箱,再试验一次,证实了此想法.
好吧,既然最后一次循环错误,直接原句循环次数减一就应该能解决问题.
使用!!VRv951:-1; 地图果真不再出错了.
(当然,后面DO循环也应该增加一句对v951变量的检测是否>0.沧版的例子就做得很细致了)
至此已经知道问题的关键.
为什么会刚好最后一个循环出错,而且真的已经没有找到箱子了?一定是程序算法漏算了.
我开始认为,是不是宝箱太多(该地图有900多个宝箱),所以出错.
于是删了又删,从900几个箱子删到500几,到300既但问题依旧.(停止试验)
又想,为啥其它地图又没有如此错误呢?
于是随机一个地图,又添加了很多箱子,奇怪的是,居然没有出现问题.
莫不是地图本身有问题吧?(开始神经了)
发呆了一阵子,突然头脑清醒起来,既然漏算了一个,那就该检测下程序漏了哪个坐标的箱子啊!真笨.
此时的第一个想法就是,很有可能是漏了第一个箱子.于是在加了句来检测有问题的地图.
!!IF&v9999=1:M^起始坐标 %V952-%V953-%V954^;
好了,果不其然,左上角的那个宝箱并不是第一个检测的箱子.(!!UN:U101/-1/-1/952;语法漏算了)
再检测没有问题的地图,最顶层最左的箱子却又可以检测得到!!!!
好了,终于知道问题的症结所在了.归纳如下:
!!UN:U101/-1/-1/952;类似的语法中(第三个参数-1代表是下一个),是获取一个物体的坐标的一种特殊方法.
但这方法有一个致命的BUG,当该类型的(这里101是箱子,后面的-1是任意)物体处于地面层最左上角时(0,0,0),
程序会直接漏掉,也就是说,语法是从(0,0,0)之后才开始检测的!
刚好昨天看到了沧版的一个很好的例子.正好用上了此类语法.
ERM功能地图上生成的随机怪物初始化时数量增加,1级和2级增加4倍,3级至7级增加2倍,数量为1的怪物不增加,数量超过4000的怪物不增加
ZVSE
!?PI;
!!FU199:P-199;
!?FU199&x1=-199;
!!UN:U54/-1/?y-1;
!!VRv1:S-1;
!!DO199/1/y-1/1&y-1>0:P199;
!?FU199&x1=199;
!!UN:U54/-1/-1/1; [留意这句]
!!OBv1/v2/v3:U?v4;
!!MA&v4>=0:Lv4/?y5;
!!MO1:G?y6;
!!FU&y6=1:E;
!!VRy7:S0;
!!VRy7&y5<=1:S4;
!!VRy7&y5>=2:S2;
!!VRy8:Sy6*y7;
!!VRy8&y8>4000:S4000;
!!MO1:Gy8;为了验证我的猜想,不妨试试在一个地图(0,0,0)的位置加入怪物,同时使用沧版的这段ERM.
这样就会在!!UN:U54/-1/-1/1; 这句上出错了.
由于有ERA的新版本,我第一时间查看了该段是否更新了.
原来已经被修正了,见下面的ERA代码(位于<78 wog - wogify.erm>文件中).!!UN:P132/?y3;
!!UN&y3=1:U101/-1/?v951;
!!VRv951:-1; reduce # of chests by 1 to fix bug (JHV)[减一是为了修正BUG]
!!VRv952:S-1;
!!DO679/1/v951/1&y3=1/v951>0:P;
值得一提的是,我个人认为直接减一不是唯一的修正方法.
事实上,UN:U获取物体坐标还有个方法,直接使用索引!
来看ERM帮助
----------------------------------------------------------------------------------------
U#1/#2/#3/#4;
获得一个物体的坐标
#1 = 物体的类型 (格式OB)
#2 = 物体的子类型(-1 = 任意)
#3 = 物体的索引 (1...N最后一个物体的索引)
#4 = 用于存储第一个坐标的v变量的索引
也就是说:v[#4]=x, v[#4+1]=y, v[#4+2]=l
举例:
U54/i/3/324; v324,v325, v326 现在存放类型54子类型i的第三个物体的坐标。
提示:
所有物体编号计算的顺序为:
从左到右,从上到下,从地面到地下。
----------------------------------------------------------------------------------------
既然我们已经使用循环了,那么循环的x16就可以担当索引的角色.
我觉得这句
!!UN:U101/-1/-1/952;
可改为
!!UN:U101/-1/x16/952;
注:后来发现这个虽然能影响第一个物体,但却严重影响到速度!使用索引的话,系统每次都要从头计算第N个位置的坐标,当地图物品较多时,就会异常缓慢!
所以直接将总数 -1 是最佳的方案!!另外,如果可以的话,地图的(0,0,0)位置最好不要放置有用的物体,以避免可能带来的问题.
好吧,测试是最好的验证.
不清楚大家是否都了解过这个BUG,故抛砖引玉一下.权当作个提醒.
[ 本帖最后由 贤知有您 于 2012-8-16 09:26 编辑 ] 好吧,我进错帖子了,对不起;ym; 那怎么才能修复这个官方脚本?
清雨悠扬的推荐设置里好像也提到过这个问题. 这个…我还是走吧
回复 3# 的帖子
就这句修复了.ERA已经修复了此BUG.在WOG中也一样.!!VRv951:-1; reduce # of chests by 1 to fix bug (JHV)[减一是为了修正BUG] 007你真是很有编程能力以及热情的一个人啊
羡慕。 确实当年我也遇到过这个问题,看了一下自己的修改记录,是2008-10-25我修正的,也是加了下面的语句解决的。
** upgrade chests
!!UN:P132/?y3;
!!UN&y3=1:U101/-1/?v951;
!!VRv951&y3=1/v951>1:-1;
!!VRv952:S-1;
!!DO679/1/v951/1&y3=1:P;
我不像LZ这么有钻研精神,我只是感觉程序漏算了一个宝箱,所以才导致出错的。因此当宝箱的数量大于1时我就把它减一,问题就解决了,经测试没有问题就这么过去了。LZ居然能找到真正的出错原因,真厉害。:good_job: 很久以前,我还只用官方ERM的时候玩一张叫windows的图也会跳这个,不过当时看LOG知道是宝箱出毛病后我就很少开那个宝箱加钱的选项了。
另外,关于为什么会出错的背后原因……其实是一个很哭笑不得的理由:
在电脑程序世界里,-1和-1是不一样的。
大家自行理解……
另外,我也理解为什么可以漏掉地表0:0,因为同样哭笑不得的留空定势思维……
[ 本帖最后由 eva2000as 于 2012-8-16 09:04 编辑 ] UN:U#1/#2/-1/#4中-1的描述是下一个,问题在于他是如何判断的第一个
也就是说,UN:U#1/#2/-1/#4会不会的对UN:U#1/#2/#3/#4中的#3产生反映,如果用UN:U#1/#2/3/#4直接检测
第三个单位后,-1意味着第四个单位还是从头开始检测,不知007是否研究过
回复 9# 的帖子
我又仔细看了下帮助文件,原来帮助文件已经有所描述,关于使用 -1 (下一个)的概况.而且如果用索引来完成循环,将会使运行速度变慢(所以总数-1是最佳方案)
--------------------------以下帮助的内容-----------------------------
在标准语法中(索引=1...N),UN:U将从地图的开头处搜寻每一个同样类型的物体然后跳过它,直到找到目标索引的物体。在一幅大地图上,这会是一个漫长的过程,尤其是地图上有很多同类物体时。
通过新的语句(索引=-1或-2),坐标将会储存在v[#4]/v[#4+1]/v[#4+2],然后,在下一个同样的接收器时搜寻这个坐标的前一个或下一个物体,而不是重新开始搜寻。这意味着会大大加快处理速度。但是这同样意味着,你不能改变这些v变量,否则下次使用这种语句就不灵了。
回复 10# 的帖子
按这样描述的话UN:U#1/#2/#3/#4的内容并不会影响UN:U#1/#2/-1/#4的结果,即使它们使用同一个v变量
回复 11# 的帖子
不是吧.我觉得只要第四个参数相同,而且3个V变量是正确的存在,那么-1检测下个的语句,就会受到影响的.
等下有空测试一下才行. 我用以下脚本测试.在左上角 (1,0,0) (2,0,0) (3,0,0) 分别放置怪物.
ZVSE
!?PI;
!!UN:U54/-1/1/1; [第1个生物]
!!IF:M^第1个生物坐标%V1-%V2-%V3^;
!!UN:U54/-1/2/1; [第二个生物]
!!IF:M^第2个生物坐标%V1-%V2-%V3^;
!!UN:U54/-1/-1/1;
!!IF:M^下一个生物坐标%V1-%V2-%V3^;
!!VRv1:S1;
!!VRv2:S0;
!!VRv3:S0;
!!UN:U54/-1/-1/1;
!!IF:M^下一个生物坐标%V1-%V2-%V3^;
测试完毕..
结果分别是
1-0-0
2-0-0
3-0-0 [说明前面的索引语句对后面的-1语句生效]
2-0-0[说明直接更改V变量语句,也对后面的 -1语句生效]
所以用-1之类的语句检测下一个,是受第四个参数影响的.(当然3个V变量都要正确)
只要V变量正确,程序就会从此坐标的下一个坐标开始检测该物体.
回复 13# 的帖子
原因清楚了,v变量默认为0,所以UN:U#1/#2/-1/#4必然跳过(0,0,0)这样的话用UN:U#1/#2/#3/#4读取第一个地址,然后用UN:U#1/#2/-1/#4读取下一位可以解决这个问题
测试辛苦了
回复 14# 的帖子
可以这么理解.应该说,是语法判定 V变量代表的坐标无效时,直接从(0,0,0)开始.
同时我也明白到,为何要使用语句
!!VRv952:S-1;
这句重设V变量,是为了从头开始检测物体..
页:
[1]