本章主要介绍record类型变量和list类型变量以及变量别名的自身嵌套和相互嵌套
6.1 record类型变量
实例一:
#var skill.name "玄铁剑法"
#var skill.id "xuantie-jia"
#var skill.level 310
上面3个命令将一个技能的中文名字、英文名字和等级全部保存到了一个变量@skill中
#say @skill///@skill.name///@skill.id///@skill.level
显示结果为:name玄铁剑法idxuantie-jialevel310///玄铁剑法///xuantie-jia///310
也有专门针对record类型变量的显示命令#showdb,注意没有#saydb这个命令
#showdb @skill,显示结果一共3行如下:
name: 玄铁剑法
id: xuantie-jia
level: 310
我们把@skill称为一个database record,把name、id、level称为key,而"玄铁剑法"、"xuantie-jian"、"310"分别为对应key的值。
record类型的变量的优点在于变量的含义更加清楚,并且相关的信息都保存在一个变量中,对这些信息的使用更加方便.
对record类型的变量进行操作的相关命令非常多,下面通过一些例子来简单说明下
(1)#say %db(@skill,level) 完全等同于#say @skill.level
(2)#say %iskey(@skill,id)//%iskey(@skill,shuliandu)
%iskey(record,key)返回record中key的序号,如果不存在返回0
上面例子中id是第二个key,shuliandu不是@skill的key,所以显示为2//0
(3)#say %addkey(@skill,shuliandu,10002)//%iskey(@skill,shuliandu)
显示为:name玄铁剑法idxuantie-jialevel310shuliandu10002//0
%addkey可以在record中添加key和key对应的值,但是并不会改变record的内容,所以%iskey(@skill,shuliandu)的显示结果仍然为0
如果需要改变record的内容,可以用下面的3个命令中的任意一个
#addkey skill shuliandu 10002
#var skill.shuliandu 10002
#var skill %addkey(@skill,shuliandu,10002)
跟添加key类似,删除key的命令有#delkey,%delkey,用法类似,这里就不做介绍了
(4)#say %numkeys(@skill) 显示@skill中key的个数
这里介绍的一些命令已经跟DataBase有点沾边了。在zmud555和721版本中提供DB和Map,并且有非常多的命令配合DB和Map来使用。考虑到DB和Map的制作及使用讲起来需要大量篇幅,同时还要配合大量图片,并且在机器人制作过程中并非不可缺少,所以此文暂时不涉及这2方面内容。以后如有需要,可能会专门开贴来介绍DB和Map。
6.2 list类型变量
将一列信息保存在一个变量中,每个单独的信息用"|"间隔开来,每项信息称为list类型变量的item
实例一:做一个trigger来拾取游戏中掉落的随机装备
#var baobei "剑|刀|杖|鞭|斧|枪|锤|戟|匕|铠甲|盔|腰带|靴|项链|戒指|披风|袍|护腕|手套|盾"
#var baobei2 "sword|blade|staff|whip|axe|spear|hammer|halberd|dagger|armor|head|waist|boots|necklace|ring|surcoat|cloth|wrists|hands|shield"
#tri {从@dbrname身上掉了出来一*之(*)$} {get %item(@baobei2,%ismember(%1,@baobei))}
在这个例子中@baobei中保存了所有随机装备的种类,@baobei2中保存所有随机装备的id,并且注意到@baobei和@baobei2中种类和id是一一对应的。
%ismember(%1,@baobei)返回%1在@baobei中的位置。比如如果掉落刀返回值为2,掉落鞭返回值为4
如果%1不在@baobei中,返回为0
%item(@baobei2,%ismember(%1,@baobei)),通过%ismember(%1,@baobei)的返回值得到掉落的随机装备的id
注:现在这个例子已经没有意义了,应该写一些触发来drop垃圾,不过这个例子中的方法还是很好的.
实例二:输入sk命令,抓取所有技能的中文名字英文名字技能等级保存到变量中
#tri {你目前所学过的技能:} {#var skname {};#var sklevel {};#var skills {}}
//将@skname,@sklevel,@skills清空
#tri {│%s(*)%s~((*)~)%s-*%s(%d)~/} {#if (%numitems(@skname)=0) {#var skname %1} {#var skname %additem(%1,@skname)};#if (%numitems(@skils)=0) {#var skills %2} {#var skills %additem(%2,@skills)};#if (%numitems(@sklevel)=0) {#var sklevel %3} {#var sklevel %additem(%3,@sklevel)}}
//%numitems()返回list类型变量中item的个数
//抓取中文名字英文名字和技能等级进行赋值,如果变量为空就直接赋值,否则作为变量的一个item添加进去
//%additem和#additem类似于前面讲过的%addkey和#addkey
//对每个技能都触发,并且抓取到的中文名字英文名字和技能等级在变量中的位置都是对应的
再定义几个函数就可以了
#fu name {%item(@skname,%ismember(%1,@skills))}
#fu level {%item(@sklevel,%ismember(%1,@skills))}
#say @name("xuantie-jian")//@level("xuantie-jian")级
显示为:玄铁剑法//310级
实例三:输入semote,抓取所有的表情命令保存到变量中
输入semote,每一行有5个表情命令,每个命令由字母和数字组成,需要用%a通配
#tri {^(%a)%s(%a)%s(%a)%s(%a)%s(%a)$} {#additem emotes %1;#additem emotes %2;#additem emotes %3;#additem emotes %4;#additem emotes %5}
//list类型变量中item的个数是没有限制的,把所有的表情都保存到@emotes中
然后你可以通过%random %disc等函数来选取随机表情使用
#say %numitems(@emotes) 显示出表情的个数
注意:举个例子来说明%additem和#additem的另一个区别
#var path {n|e|sw|se|e|u|enter boat|out|w}
#say %additem("sw",@path) 显示为n|e|sw|se|e|u|enter boat|out|w|sw
#say %additem(@path,"sw") 显示为sw|n|e|sw|se|e|u|enter boat|out|w
#say @path 显示为n|e|sw|se|e|u|enter boat|out|w
#additem path "sw";#say @path 显示为n|e|sw|se|e|u|enter boat|out|w
//如果要添加的item已经存在于list变量中,则添加无效
#additem path "enter";#say @path 显示为n|e|sw|se|e|u|enter boat|out|w|enter
简而言之,#additem不允许item重复,如果有重复则命令无效.需要添加重复的item,请用%additem
对list类型变量进行操作的命令除了上面提到的%item、%numitems、%ismember、%additem、#additem,还有#delitem、#delnitem、%delitem、%dups、%sort
#delitem list item 删除指定item,如果变量中有多个重复的item,则删除所有重复的item
%delitem(item,@list) 删除指定item,如果变量中有多个重复的item,只删除第一个的item
#delnitem list n 从@list中删除第n个item
%dups 去掉变量中重复的item,只保留第一个item
#SHOW %dups(Athos|Bertrand|Caesar|Bertrand|Caesar|Bertrand)
显示为Athos|Bertrand|Caesar
%sort 对变量中的item按照字母和数字进行排序
6.3 嵌套
zmud允许variable,alias和function互相嵌套,来完成更复杂的事情
上一章中已经介绍了一个function的嵌套
#fu fact {%if(%1<=1,1,%1*@fact(%eval(%1-1)))}
其实就是定义了一个阶乘函数,不用嵌套很难计算阶乘
实例一:定义一个函数,计算exp支持的技能等级上限
#fu maxlevel %if((%1*%1*%1/10)<%2,@maxlevel(%eval(%1+1),%2),%1)
#say @maxlevel(1,100000)//@maxlevel(100,3000000)//@maxlevel(700,50000000)
显示为100/311/794,分别为100k,3m,50m exp对应的技能等级上限
这里第一个参数的作用是保守的预估一个等级,一定要比最大技能等级低,可以减少计算次数,提高计算速度,第二个参数就是要计算的经验值
实例二:用alias来计算exp支持的技能等级上限
#alias maxlevel {#var n 1;#while ((@n*@n*@n/10)<%1) {#add n 1};#say 技能最高为@n级}
maxlevel 3000000 显示为:技能最高为312级
不使用嵌套,但是用到了#while循环语句.#while功能也很强大,但同时也有我不喜欢的缺点,所以我一般避免使用#while,后面章节中会讲到#while的缺点
#alias maxlevel {#if ((%1*%1*%1/10)<%2) {maxlevel %eval(%1+1) %2} {#say 技能最高为%1级}}
使用嵌套同样可以达到目的,你可以随意预估一个值作为%1,要计算的经验值作为%2
这几个例子中,用定义函数的方法来计算速度最快,比另外2种方法要快几倍,推荐使用
总结:个人认为,本章和下一章将要讲到的内容是所有章节中最重要的2章,可以算是从中级水平到高级水平的一个转折。机器人编写中用到record,list以及嵌套,能完成很多复杂的事情.后面的章节中将会大量的出现record,list以及嵌套.