佳丽云

英雄无敌3-WoG中文站

 找回密码
 英雄注册|Register
查看: 4868|回复: 14

关于UN:U命令产生BUG的研究

[复制链接]
  • TA的每日心情
    郁闷
    2015-6-6 16:12
  • 签到天数: 52 天

    连续签到: 1 天

    [LV.5]女巫

    4949

    回帖

    3万

    金币

    35

    精华

    超级版主

    Rank: 11Rank: 11Rank: 11Rank: 11

    积分
    34677

    论坛守望者论坛元老杰出贡献

    发表于 2012-8-15 20:05:39 | 显示全部楼层 |阅读模式
    关于UN:U命令产生BUG的研究


    首先,这个BUG也许好早就有人发现.不过我是今天才认识到的,和大家分享一下研究心得.
    事情起于对当年一幅WOG化出错地图的研究.
    地图的名字是<Arena of death>,里面拥有很多宝箱和各种资源.当年玩时按照一般惯例不开启<替换物体>选项,但WOG化后仍然出错,由于当时不太懂ERM语法.但那句cannot find more objects 一直很深刻.出错后如果继续玩,后期会有意想不到的现象,比如特长兵种的,攻防都固定为400几以上了.
    1.JPG



    最近找到了那张地图重玩,问题依旧.此时已经比较容易找到出错的位置,是选项<一些箱子会有更多的钱>的问题,禁用了就没出错信息.
    该选项对应的ERM是script00.erm中的以下语句:
    1. ** upgrade chests

    2. !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]检测选项是否开启
    3. !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
    4. !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
    5. !!DO679/1/v951/1&y3=1:P; [upgrade some of them]始循环所有宝箱,并使箱子有机会获得更多钱
    6. ** function to possibly upgrade a treasure chest

    7. !?FU679; [使箱子获得更多钱的函数]
    8. !!UN:U101/-1/-1/952; [get x/y/l of yellow square of chest into v952-v954]出错在此句上
    9. !!VRy1:S0 R99; [roll percentile dice]
    10. !!CH952&y1<8:B5; [8% chance for 2500 gold chest]
    11. !!CH952&y1>97:B6; [2% chance for 3000 gold chest]

    12. ** end of function
    复制代码

    乍看句子都很正常,为什么会出错呢?联想起cannot find more objects,估计是因为没有找到对应的物体(宝箱).
    于是加入了在两段中加入几句来看看到底什么时候出错.
    1. !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]
    2. !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
    3. !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
    4. !!VRv9999:S0; [增加]
    5. !!IF:M^宝箱总数 %V951^; [增加]
    6. !!DO679/1/v951/1&y3=1:P; [upgrade some of them]
    7. ** function to possibly upgrade a treasure chest
    8. !?FU679;
    9. !!VRv9999:+1; [增加]
    10. !!UN:U101/-1/-1/952; [get x/y/l of yellow square of chest into v952-v954]

    11. !!VRy1:S0 R99; [roll percentile dice]
    12. !!CH952&y1<8:B5; [8% chance for 2500 gold chest]
    13. !!CH952&y1>97:B6; [2% chance for 3000 gold chest]
    14. ** 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)之后才开始检测的!



    刚好昨天看到了沧版的一个很好的例子.正好用上了此类语法.
    1. ERM功能地图上生成的随机怪物初始化时数量增加,1级和2级增加4倍,3级至7级增加2倍,数量为1的怪物不增加,数量超过4000的怪物不增加
    2. ZVSE
    3. !?PI;
    4. !!FU199:P-199;
    5. !?FU199&x1=-199;
    6. !!UN:U54/-1/?y-1;
    7. !!VRv1:S-1;
    8. !!DO199/1/y-1/1&y-1>0:P199;

    9. !?FU199&x1=199;
    10. !!UN:U54/-1/-1/1; [留意这句]
    11. !!OBv1/v2/v3:U?v4;
    12. !!MA&v4>=0:Lv4/?y5;
    13. !!MO1:G?y6;
    14. !!FU&y6=1:E;
    15. !!VRy7:S0;
    16. !!VRy7&y5<=1:S4;
    17. !!VRy7&y5>=2:S2;
    18. !!VRy8:Sy6*y7;
    19. !!VRy8&y8>4000:S4000;
    20. !!MO1:Gy8;
    复制代码
    为了验证我的猜想,不妨试试在一个地图(0,0,0)的位置加入怪物,同时使用沧版的这段ERM.
    这样就会在!!UN:U54/-1/-1/1; 这句上出错了.
    2.JPG





    由于有ERA的新版本,我第一时间查看了该段是否更新了.
    原来已经被修正了,见下面的ERA代码(位于<78 wog - wogify.erm>文件中).
    1. !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]
    2. !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
    3. !!VRv951:-1; reduce # of chests by 1 to fix bug (JHV)[减一是为了修正BUG]
    4. !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
    5. !!DO679/1/v951/1&y3=1/v951>0:P; [upgrade some of them]
    复制代码


    值得一提的是,我个人认为直接减一不是唯一的修正方法.
    事实上,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; [get x/y/l of yellow square of chest into v952-v954]
    可改为
    !!UN:U101/-1/x16/952;
    注:后来发现这个虽然能影响第一个物体,但却严重影响到速度!使用索引的话,系统每次都要从头计算第N个位置的坐标,当地图物品较多时,就会异常缓慢!
    所以直接将总数 -1 是最佳的方案!!另外,如果可以的话,地图的(0,0,0)位置最好不要放置有用的物体,以避免可能带来的问题.

    好吧,测试是最好的验证.
    不清楚大家是否都了解过这个BUG,故抛砖引玉一下.权当作个提醒.

    [ 本帖最后由 贤知有您 于 2012-8-16 09:26 编辑 ]

    评分

    2

    查看全部评分

  • TA的每日心情
    慵懒
    2019-8-17 09:46
  • 签到天数: 1158 天

    连续签到: 2 天

    [LV.10]圣龙

    2万

    回帖

    91万

    金币

    7

    精华

    论坛嘉宾

    守望论坛的稻草人

    Rank: 9Rank: 9Rank: 9

    积分
    87641

    社区QQ达人论坛守望者金牌裁判杰出贡献魅力之星TE联赛冠军

    发表于 2012-8-15 20:12:14 | 显示全部楼层
    好吧,我进错帖子了,对不起

    评分

    1

    查看全部评分

  • TA的每日心情
    开心
    2020-9-19 16:27
  • 签到天数: 7 天

    连续签到: 1 天

    [LV.3]火元素使者

    9896

    回帖

    64万

    金币

    19

    精华

    管理员

    风侠

    Rank: 12Rank: 12Rank: 12

    积分
    52327

    论坛元老魅力之星封魔玩家

    发表于 2012-8-15 20:22:05 | 显示全部楼层
    那怎么才能修复这个官方脚本?

    清雨悠扬的推荐设置里好像也提到过这个问题.
  • TA的每日心情
    无聊
    2024-4-29 21:42
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]野猪

    2735

    回帖

    11万

    金币

    1

    精华

    6级 Legendary Hero

    Rank: 6Rank: 6

    积分
    11623

    退役版主

    QQ
    发表于 2012-8-15 20:29:08 | 显示全部楼层
    这个…我还是走吧
  • TA的每日心情
    郁闷
    2015-6-6 16:12
  • 签到天数: 52 天

    连续签到: 1 天

    [LV.5]女巫

    4949

    回帖

    3万

    金币

    35

    精华

    超级版主

    Rank: 11Rank: 11Rank: 11Rank: 11

    积分
    34677

    论坛守望者论坛元老杰出贡献

     楼主| 发表于 2012-8-15 21:09:39 | 显示全部楼层

    回复 3# 的帖子

    就这句修复了.ERA已经修复了此BUG.在WOG中也一样.
    !!VRv951:-1; reduce # of chests by 1 to fix bug (JHV)[减一是为了修正BUG]
  • TA的每日心情

    昨天 19:20
  • 签到天数: 2611 天

    连续签到: 37 天

    [LV.Master]伴坛终老

    1万

    回帖

    19万

    金币

    0

    精华

    白银会员

    Rank: 5Rank: 5

    积分
    97743

    魅力之星

    QQ
    发表于 2012-8-15 22:58:25 | 显示全部楼层
    007你真是很有编程能力以及热情的一个人啊

    羡慕。
    该会员没有填写今日想说内容.
  • TA的每日心情
    奋斗
    昨天 20:25
  • 签到天数: 657 天

    连续签到: 3 天

    [LV.9]龙巫妖

    89

    回帖

    4万

    金币

    0

    精华

    6级 Legendary Hero

    Rank: 6Rank: 6

    积分
    8911
    发表于 2012-8-15 23:32:36 | 显示全部楼层
    确实当年我也遇到过这个问题,看了一下自己的修改记录,是2008-10-25我修正的,也是加了下面的语句解决的。

    ** upgrade chests
    !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]
    !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
    !!VRv951&y3=1/v951>1:-1;
    !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
    !!DO679/1/v951/1&y3=1:P; [upgrade some of them]

    我不像LZ这么有钻研精神,我只是感觉程序漏算了一个宝箱,所以才导致出错的。因此当宝箱的数量大于1时我就把它减一,问题就解决了,经测试没有问题就这么过去了。LZ居然能找到真正的出错原因,真厉害。

    评分

    2

    查看全部评分

  • TA的每日心情
    奋斗
    2015-1-22 08:29
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]野猪

    919

    回帖

    1万

    金币

    1

    精华

    论坛嘉宾

    掘坑者的铁锹

    Rank: 9Rank: 9Rank: 9

    积分
    1522

    退役版主

    发表于 2012-8-16 08:58:44 | 显示全部楼层
    很久以前,我还只用官方ERM的时候玩一张叫windows的图也会跳这个,不过当时看LOG知道是宝箱出毛病后我就很少开那个宝箱加钱的选项了。

    另外,关于为什么会出错的背后原因……其实是一个很哭笑不得的理由:
    在电脑程序世界里,-1和-1是不一样的。
    大家自行理解……
    另外,我也理解为什么可以漏掉地表0:0,因为同样哭笑不得的留空定势思维……

    [ 本帖最后由 eva2000as 于 2012-8-16 09:04 编辑 ]

    评分

    1

    查看全部评分

    某真祖的酒馆留言簿:据说在诅咒之地上作战时,怪物强化III无法完全生效。
    某真祖的酒馆留言簿:魔镜大法能使一些生物施法无效但不能反射。

    该用户从未签到

    399

    回帖

    1万

    金币

    1

    精华

    5级 Honorable Hero

    Rank: 5Rank: 5

    积分
    3156

    退役版主

    发表于 2012-8-16 09:00:38 | 显示全部楼层
    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是否研究过

    评分

    1

    查看全部评分

  • TA的每日心情
    郁闷
    2015-6-6 16:12
  • 签到天数: 52 天

    连续签到: 1 天

    [LV.5]女巫

    4949

    回帖

    3万

    金币

    35

    精华

    超级版主

    Rank: 11Rank: 11Rank: 11Rank: 11

    积分
    34677

    论坛守望者论坛元老杰出贡献

     楼主| 发表于 2012-8-16 09:25:25 | 显示全部楼层

    回复 9# 的帖子

    我又仔细看了下帮助文件,原来帮助文件已经有所描述,关于使用 -1 (下一个)的概况.
    而且如果用索引来完成循环,将会使运行速度变慢(所以总数-1是最佳方案)
    --------------------------以下帮助的内容-----------------------------
    在标准语法中(索引=1...N),UN:U将从地图的开头处搜寻每一个同样类型的物体然后跳过它,直到找到目标索引的物体。在一幅大地图上,这会是一个漫长的过程,尤其是地图上有很多同类物体时。
    通过新的语句(索引=-1或-2),坐标将会储存在v[#4]/v[#4+1]/v[#4+2],然后,在下一个同样的接收器时搜寻这个坐标的前一个或下一个物体,而不是重新开始搜寻。这意味着会大大加快处理速度。但是这同样意味着,你不能改变这些v变量,否则下次使用这种语句就不灵了。

    该用户从未签到

    399

    回帖

    1万

    金币

    1

    精华

    5级 Honorable Hero

    Rank: 5Rank: 5

    积分
    3156

    退役版主

    发表于 2012-8-16 09:41:31 | 显示全部楼层

    回复 10# 的帖子

    按这样描述的话
    UN:U#1/#2/#3/#4的内容并不会影响UN:U#1/#2/-1/#4的结果,即使它们使用同一个v变量
  • TA的每日心情
    郁闷
    2015-6-6 16:12
  • 签到天数: 52 天

    连续签到: 1 天

    [LV.5]女巫

    4949

    回帖

    3万

    金币

    35

    精华

    超级版主

    Rank: 11Rank: 11Rank: 11Rank: 11

    积分
    34677

    论坛守望者论坛元老杰出贡献

     楼主| 发表于 2012-8-16 09:43:44 | 显示全部楼层

    回复 11# 的帖子

    不是吧.
    我觉得只要第四个参数相同,而且3个V变量是正确的存在,那么-1检测下个的语句,就会受到影响的.
    等下有空测试一下才行.
  • TA的每日心情
    郁闷
    2015-6-6 16:12
  • 签到天数: 52 天

    连续签到: 1 天

    [LV.5]女巫

    4949

    回帖

    3万

    金币

    35

    精华

    超级版主

    Rank: 11Rank: 11Rank: 11Rank: 11

    积分
    34677

    论坛守望者论坛元老杰出贡献

     楼主| 发表于 2012-8-16 10:00:28 | 显示全部楼层
    我用以下脚本测试.在左上角 (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变量正确,程序就会从此坐标的下一个坐标开始检测该物体.

    该用户从未签到

    399

    回帖

    1万

    金币

    1

    精华

    5级 Honorable Hero

    Rank: 5Rank: 5

    积分
    3156

    退役版主

    发表于 2012-8-16 10:42:52 | 显示全部楼层

    回复 13# 的帖子

    原因清楚了,v变量默认为0,所以UN:U#1/#2/-1/#4必然跳过(0,0,0)
    这样的话用UN:U#1/#2/#3/#4读取第一个地址,然后用UN:U#1/#2/-1/#4读取下一位可以解决这个问题
    测试辛苦了

    评分

    1

    查看全部评分

  • TA的每日心情
    郁闷
    2015-6-6 16:12
  • 签到天数: 52 天

    连续签到: 1 天

    [LV.5]女巫

    4949

    回帖

    3万

    金币

    35

    精华

    超级版主

    Rank: 11Rank: 11Rank: 11Rank: 11

    积分
    34677

    论坛守望者论坛元老杰出贡献

     楼主| 发表于 2012-8-16 10:56:36 | 显示全部楼层

    回复 14# 的帖子

    可以这么理解.
    应该说,是语法判定 V变量代表的坐标无效时,直接从(0,0,0)开始.
    同时我也明白到,为何要使用语句
    !!VRv952:S-1;
    这句重设V变量,是为了从头开始检测物体..
    ahome_bigavatar:guest
    ahome_bigavatar:welcomelogin
    您需要登录后才可以回帖 登录 | 英雄注册|Register

    本版积分规则

    捐赠
    关注我们,英3Mod一网打尽!

    WoG中文站 ( 辽B2-20210485-10 )|辽公网安备 21128202000228 号

    GMT+8, 2024-11-22 15:48 , Processed in 0.938767 second(s), 19 queries , Gzip On, File On.

    Powered by Discuz! X3.4

    Copyright © 2004-2022, Beijing Second Sight Technology Co., LTD.

    快速回复 返回顶部 返回列表