MUD-武林MUD资料站

 找回密码
 注册

QQ登录

只需一步,快速开始

开启左侧

[教程] 新手机器人速成宝典(中级篇)

[复制链接]
南极熊 发表于 2010-9-8 19:58:11 | 显示全部楼层 |阅读模式
第五章 按钮﹑系统变量和函数
第六章 variable和alias的更多应用
第七章 掌控时间
第八章 提高机器人稳定性和适用面
第九章 丰富你的机器人

第五章 buttons﹑系统变量﹑function

5.1 button

按钮(buttons)是很实用的一个功能,不光应用于半自动的机器人让游戏过程更加便捷,也用于全自动机器人,让人为修改某些变量更加简单.

按钮有3个要素:Caption,Commands(zmud721中这个要素被称为Value)和Class.其中Caption是按钮的名字,显示在按钮中间;Commands保存有一系列命令,当你点击按钮的时候,Commands中的内容就作为指令发送出去;Class是按钮所属的类,只是为了加载的时候方便。

Caption后面的颜色图标可以更改按钮的颜色,主选项卡Button States里可以选择按钮的种类;Postion/Size选项卡里的内容可以更改按钮的大小和位置;Advanced选项卡里Bitmap File可以选择一个自定义图标显示在按钮上,并且zmud721还有自带图标供选择。

按钮的种类:一共四种Push﹑Toggle﹑Separator和Multistate
Push:点击一下执行一次Commands中的命令
Toggle:分为button up和button down2种状态,分别储存有2个命令串;每次点击都会执行对应状态中储存的命令串并且从一种状态改变为另一种状态。简单点说就相当于2个按钮。
Separator:仅仅作为分隔**按钮的工具来使用,不包含任何命令。
Multistate:一个下拉式按钮,点击之后会出现下拉列表,然后选择,不同的选择执行不同的命令。

在Buttons列表里有button的序号,#button 序号 这个命令等同于鼠标点击一次按钮,这个命令可以用于alias,variable,marco和trigger中。**与button有关的命令有#yesno,#pr和#pick,这3个命令将在第八章中介绍。另外#button也可用于新建按钮,鉴于语法格式过于复杂,这里略过了。

按钮的功能可以说非常丰富,可以做出很漂亮的界面。
这里要推荐inspector同学的一篇文章http://telweb.pkuxkx.net/forum/thread-6501-1-3.html 小蜜蜂机器人(新手专用)

5.2 系统变量
主要介绍最实用的%ctime,%i和%random

%ctime表示你的连线时间,单位是秒

实例一:我需要机器人计算吐纳时每小时增加精力的速度。
#tri {你的精力上限增加了!!} {#add jingli_add 1;#var tuna_speed [@jingli_add*3600/%ctime];#show 每小时获得@tuna_speed点精力!}

%ctime还可用于萧峰,万安塔,胡一刀,护镖,护送和朝廷守门等任务,能接任务时由机器人自动提醒,具体在第七章中专门介绍

%i主要用于各种命令中,配合#number和#loop来使用,也用于专门针对数据库变量、record类型变量和list类型变量的命令中,这些命令主要有#loopdb,#forall等等
比如 #5 kill menggu bing %i等价于kill menggu bing 1;kill menggu bing 2;kill minggu bing 3;kill menggu bing 4;kill menggu bing 5

#number和#loop都是一次性发送数个相同的命令,区别在于变量可以用于#loop中来控制发送命令的次数,而#number中的number一定要是一个实际的阿拉伯数字

错误用法:#var number 5;#@number kill menggu bing %i
正确用法:#var number 5;#loop @number {kill menggu bing %i}
注意事项:#var number 0;#loop @number {kill menggu bing %i}实际效果是kill menggu bing 1,也就是说#loop至少会执行一次,@number中的值为0或者负值或者干脆是字符串乃至汉字,都是执行1次命令,zmud不会抱错,可以自行试验。

#loop命令在我发的领悟机器人中被用到,用来改变领悟或者练习的次数,以适用不同exp层次的id。

%random产生一个0-99的随即数字,%random(1,5)产生一个1-5的随机数,结合#case命令来发送随机命令

#case @variable {cmd1} {cmd2} {cmd3} {cmd4} {cmd5}...可以根据@variable值的不同来发送不同的命令,比如@variable值为3,第3个括号中的命令cmd3会被执行,**命令都不执行。

另外%time和%dice有兴趣也可以看一下,举几个例子简单说下
#say %time()显示为星期三 七月 22, 2009 2:14:14 am
#say %time(c)显示为2009/7/22 2:16:12
#say %time("aaaa tttt")显示为星期三 2:26:03
%time()的括号中可以使用参数来改变显示内容,这些参数有a(星期)、d(日期)、m(月份)、y(年)、e(年)、t(时分秒)、h(小时)、 n(分)和s(秒),下面给个复杂点的例子,有兴趣可以自行试验看下显示结果。
#FORALL {a|d|m|y|e|g|t|h|n|s} {#SH %i: %time(%i) | %time(%i%i) | %time(%i%i%i) | %time(%i%i%i%i)}
这个例子基本包含了所有的格式,%i依次等于a、d、m、y、e、g、t、h、n、s,%time()的括号中分别用1-4个%i来显示不同详细程度的内容。

%dice(2d6+2)显示为掷2个6面色子的和再加上2,是一个随机结果,()中用到的格式为xdy+n,表示"x个y面色子+n",相关变量有%dicemin()、%dicemax()、%diceavg()、%dicedev()。

**系统变量还有很多,作用都不大,不感兴趣的可以跳过。下面只列举一些,太多了不可能全面的,具体可以#help 自行查找。
%action 最后一次触发所执行的命令。   
%cr 换行。  
%def 当前使用的特殊字符。  
%host 当前连线MUD的IP地址。   
%lastcom 最后被执行的命令。   
%lastcom2 倒数第二个被执行的命令。  
%lastcom3 倒数第三个被执行的命令。  
%line 从MUD中得到的最后一行文本。  
%line2 从MUD中得到的倒数第二行文本。   
%line3 从MUD中得到的倒数第三行文本。   
%port 当前连线的端口号。
%selected 当前选中的文本。可用于speed menu的制作,通过鼠标点击来发出包含选中文本的命令
%selline 当前选中的行。可用于speed menu的制作
%selword 当前选中的单词。可用于speed menu的制作
%title 当前MUD的标题。   
%trigger 最近一次被触发的行。   
%window 当前窗口的标题。

5.3 fuction(函数)

zmud允许自定义函数,命令为#function,#fu为命令的缩写形式.可以简单的把函数理解为带参数的变量.还是用实际的小例子来说明函数的用法.

实例1:#fu sum %eval(%1+%2)
这里%eval是系统自带函数,作用等于[ ],负责运算并且返回运算结果
#say @sum(100,40)显示为140
sum在这里为一个自定义函数,包含2个参数,用法相当于带参数的变量,@sum()为函数的值

实例2:#fu min %if(%1<%2,%1,%2)
这里定义了一个函数min,作用是选择2个数中较小的数
%if为系统自带的条件函数,语法为%if(表达式,true-value,false-value),如果表达式为真,返回true-value,否则返回false-value
#say @min(5,7)显示为5
#say @min(20,11)显示为11

实例3:#fu fact {%if(%1<=1,1,%1*@fact(%eval(%1-1)))}
这个例子要复杂些,用到了函数的自身嵌套,如果参数<=1,返回1,否则返回"参数*@face(参数-1)",然后再对@fact(参数-1)重复上面的条件运算,最终的结果就是"参数*(参数-1)*(参数-2)*...*1",其实就是一个阶乘运算.
#say [@fact(5)]显示为120

函数很多时候用起来很方便,使你的机器人更容易看懂,修改起来当然就更容易
比如在上一章打坐吐纳机器人中,可以定义一个函数对气血,内力,精神,精力进行计算,确定dazuo,tuna的数值
#fu need %max(%min([(%if(%eval(%4*2-%3)<1000,[(%4*2-%3)/2],[%4*2-%3])*100+129)/@sudu],[%1-(%2+9)/10]),10)
这个函数拥有4个参数,并且包含一个变量@sudu
打坐的命令是dazuo @need(@qixue,@qixue_max,@neili,@neili_max)
吐纳的命令是tuna @need(@jingshen,@jingshen_max,@jingli,@jingli_max)
可以看到比第4章更简洁明了,省去了一大堆#var,#math,#if

另外值得一提的是,zmud的命令,系统自带变量,系统自带函数相当的多,从而使得机器人的写法多种多样,相当灵活.基本上任意一个#xxx的命令都对应有一个系统已定义好了的函数或变量%xxx()
比如#if,%if;#case,%case;#eval,%eval;#null,%null;#walk,%walk;#alias,%alias;#color,%color;#additem,%additem
太多了,实在无法一一举例,如此多的命令使zmud语言变得相当丰富灵活,我也无法做到全部了解并且熟练运用每一个命令。但是毫无疑问,知道的越多,做机器人就越容易。你知道多少对这样的命令,他们的用法你都知道吗?平时做机器人的时候有用过吗?


第六章 Variable和Alias的更多应用

本章主要介绍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以及嵌套.

第七章 掌控时间

7.1 #wa命令

#wa是#wait的缩写,用来延迟一个命令的执行.

用法一:延迟的具体时间以毫秒为单位指定.

比如{#wa 2000;hp}作用是2秒后发送hp这个命令

#wa后面可以指定具体数字,也可以指定一个变量,用变量来控制等待的时间。

前面章节中多次使用这种用法.#wa命令太重要了,如果没有#wa,任何命令都是立即发送,容易造成机器人发狂.另外有些命令执行完毕之后人物处于 busy状态,用#wa命令来度过busy时间,#wa的时间设置应该保守一些,一般大于busy时间.

用法二:不指定时间,#wa单独使用

实例一:{study book for 1;hp;#wa;exert regenerate}
在zmud 462和555两个版本中,运行结果为
> study book for 1
hp
你的「基本剑法」进步了!
exert regenerate
你从身上拿出一本华山剑谱准备好好研读。
你研读了一次有关基本剑法的技巧,似乎有点心得。
> ≡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━≡
【 精神 】 110   / 130    [100%]  【 精力 】 0     / 0     (+   0)
【 气血 】 48    / 97     [ 80%]  【 内力 】 0     / 0     (+   0)
【 食物 】 0     / 300    [饥饿]  【 潜能 】 234901               
【 饮水 】 0     / 300    [饥渴]  【 经验 】 75643                 
≡━━━━━━━━━━━━━━━━━━━━━━━◎北大侠客行◎━━≡
> 你略一凝神,精神看起来好多了。
study book for 1;hp;#wa3个命令同时发送执行,然后等待命令执行的结果,但是只等待一行信息,接着发送exert regenerate这个命令。#wa后面的命令得不到hp的信息,如果想让#wa后面的命令对内力气血进行判断,数一下上面的行数,至少需要连续6 次#wa,而且会被中途输出的**信息干扰,实用性为0。使用462和555版本的可以忘记这个用法。需要用**方法来替代这个用法,最简单的就是 tell自己的id,然后用tell的信息做触发。
在zmud721中运行结果为
> study book for 1
hp
你的「基本剑法」进步了!
你从身上拿出一本华山剑谱准备好好研读。
你研读了一次有关基本剑法的技巧,似乎有点心得。
> ≡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━≡
【 精神 】 110   / 130    [100%]  【 精力 】 0     / 0     (+   0)
【 气血 】 48    / 97     [ 80%]  【 内力 】 0     / 0     (+   0)
【 食物 】 0     / 300    [饥饿]  【 潜能 】 234901               
【 饮水 】 0     / 300    [饥渴]  【 经验 】 75643                 
≡━━━━━━━━━━━━━━━━━━━━━━━◎北大侠客行◎━━≡
exert regenerate
> 你略一凝神,精神看起来好多了。
具有比较高的实用性了。不同版本的差异请多多体会。

注意事项:#wa为单线流程,多个#wa同时执行时,后面的会替代前面。
试验A:在命令行里输入#wa 10000;hp,然后输入#wa 1,会发现hp被立刻执行了
试验B:在命令行反复输入{#wa 3000;hp}6次,每次输入的间隔小于3秒,会发现hp迟迟没有执行,当你停止输入时,3秒后会同时执行6次hp
请大家自行体会,做机器人时应该尽量避免多个#wa同时执行,另外可以重新输入#wa xxx来延长或者缩短前面已经输入的#wa命令。这个虽然是#wa命令的不足之处,但是仍然可以被我们利用。

因为#wa单线流程的特点,决定了#wa只用于简单的控制时间。

7.2 计时器
点击菜单Actions->计时器来设置计时器,有3个要素组成:Timer Interval,Timeout Margin和Timeout Command。

举例来说,设置Timer Interval为10,Timeout Margin为2,Timeout Command为hp,点击Start之后,zmud开始循环倒计时10秒,当计时至2秒时,执行hp这个命令。

这是另外一个控制时间的工具,最大的优点是稳定,我喜欢称它为计时器。准确地倒计时,准确地执行命令,不受到机器人的影响。缺点在于一个窗口只能设置一个 计时器,一般只用在最关键的地方。

相关命令#timer on,#timer off,#ts和#tz等。
#timer on :打开计时器
#timer off:关闭计时器
#ts 数字:  设置Timer Interval中的值
#tz:        重置计时器的时间,让他重新开始计时
以上4个命令被用于trigger,alias中用来对计时器进行操作.

注意:zmud 555在加载**机器人时,不同的时间器之间会发生干扰,计时器的3要素都会发生改变,所以建议Timeout Command中的值统一填为timer,并且新建一个alias timer来保存计时结束需要执行的命令串。

实例二:胡一刀接任务的时间间隔为10分钟,10分钟到了的时候由机器人提醒
计时器中Timer Interval设置为600秒,Timeout Margin设置为5秒,Timeout Command设置为{#say 可以接任务了!}
#tri {胡一刀说道:『我收到消息,听说&hydaddress有盗宝人&dbrname~(&dbr~)找到了闯王宝藏的地图} {#tz}

实例三:用#wa来实现计时器的功能,这样你就拥有相当于2个计时器了。
#alias ticktimer {#wa 10000;hp;ticktimer}
如果你在命令行输入ticktimer,恭喜你,你有了另外一个计时器,每隔10秒就执行一次hp命令。如果你不修改ticktimer这个alias,它将永远不会停止,请用#alias ticktimer {}来停止这个时间器。

实例四:达摩院领悟,内力不足时回去睡觉
#alias lw {#if @sleep {d;sd;w;n;sleep} {#wa 500;lingwu sword 100;exert regenerate;lw}}
#tri {你的内力不够。} {#var sleep 1}
这个例子也可以用计时器来实现;zmud721中也可以直接用#wa来实现;或者用下面要讲到的#alarm来实现。zmud的灵活性使得同样的事情,可以有很多种方法完成。

zmud本身提供#while命令,但是#wa和#while混合使用时会出问题,所以我一般不用#while,而是用这种自身嵌套来实现#while的功能。

上面的2个例子都用到了alias的自身嵌套,更多的用法大家可以自己创造,在高级篇中我会大量的使用自身嵌套,使用时需要注意不要造成死循环,一定要设置一个办法让它停止;否则,唉,你的zmud已经崩溃了,重启吧!

7.3 #alarm命令(重要)

实际上#alarm是创造一个alarm类型的trigger,以时间作为触发,相关命令为#untr

命令格式为#alarm hh:mm:ss {cmds}
其中hh:mm:ss为时:分:秒,时间前面可以加上"+"或者"-",hh、mm、ss前面也可以加上*或者直接用*代替,"+" "-" "*"这3个特殊字符的含义举例说明

#alarm 2:50:00 {#say 保卫时间到了}
时间前面没有+和-,以你计算机上的时间作为触发,凌晨2点50分提示保卫时间到了

#alarm -00:00 {save}
前面加了-,以你的连线时间作为触发.时间上没有指定小时,默认为任意小时,连线时间达到整点时自动save

#alarm +01:05 {cmd}
前面加个+,则建立一个一次性trigger,触发之后自动删除.并且既不以连线时间为触发,也不以计算机时间为触发,而是从建立trigger时算起,65秒之后触发

#alarm +65 {cmd}
跟上面的#alarm +01:05 {cmd}完全相同

#alarm (2|6|10|14|18|22):50:00 {#say %eval(%i+1)点保卫时间到了}
以计算机时间作为触发,并且用"|"指定了多个小时,同时用到了(),小时被保存到了临时变量%i中。
不光能在保卫时提醒,还指出了是哪个时间点的保卫。

#alarm *10:00 {save}
没有"+""-",以计算机时间作为触发。小时未指定默认为任意,分钟指定为*10意思是10的倍数,这个trigger会在计算机时间的分钟为00、 10、20、30、40、50时自动save

#alarm -2:30:* {hp}
小时和分都有具体指定,秒为任意。这是一个每秒钟触发一次的trigger,但是仅在你连线时间为2个半小时的触发。事实上小时分和秒都可以设定为任意,看下面的例子

#alarm -* {hp}
每秒钟触发一次,永远不会停止,用#untr -*删除这个trigger

建议:使用这个命令太频繁,机器人里会有很多已经触发过的alarm类型的trigger,但是这些trigger并没有删除掉,建议创建这个 trigger的时候,统一取一个alarm的类名,这样就可以随时用#delclass alarm来删除所有的alarm类型的trigger.

实例五:胡一刀接任务的时间间隔为10分钟,10分钟到了的时候由机器人提醒
#tri {胡一刀说道:『我收到消息,听说&hydaddress有盗宝人&dbrname~(&dbr~)找到了闯王宝藏的地图} {#alarm +600 {#say 可以接任务了!}}

实例六:保卫时间自动上线
#alarm {2|6|10|14|18|22}:50:00 {#connect;@account.zhanghao;@account.mima}
#tri {【公告天下】保卫襄阳任务全部结束} {quit;#disconnect}
其中record类型变量@account中保存有帐号密码信息
#connect连接服务器,#disconnect从服务器断开

实例七:守门结束后退出,天亮前上线
#tri {你的经验增加了*!} {#var time [1440-%ctime];#alarm +@time {#connect;@account.zhanghao;@account.mima};quit;#disconnect}
//经过大米用天色做触发统计游戏中1天的时间为24分钟,因此[1440-%ctime]就是晚上的时间
//在#alarm的时间中用到了变量,这也是zmud允许的一个用法;用变量来控制时间使得#alarm这个命令的作用大大增加,对时间的控制也更加灵活

实例八:多个计时器并存
#alias tick1 {#alarm +40 {cmd1;tick1}}
#alias tick2 {#alarm +20 {cmd2;tick2}}
命令行输入tick1;tick2就建立了2个计时器,分别是20秒计时和40秒计时
计时存在时输入tick1或者tick2可以重置计时,相当于#tz命令
#untr +40或者#untr +20可以删除这2个alarm类型的trigger,相当于#timer off

实例九:#tri {林震南说道:「你上次运镖太辛苦了,下去休息休息吧。」} {#alarm +5 {ask lin about job}}
这个例子曾在第二章中出现过,用的是#wa 5000,需要打开关闭触发来防止误触发
这里用#alarm,就不需要那么麻烦,无论如何也不会出现同时输入多个"ask lin about job"的情况
但是新的问题是:如果有人一直在林这里制造干扰,命令就发不出去了。所以还是有必须要打开关闭触发。

注一:#alarm是一个功能更为强大的命令,和#wa,计时器一起构成了zmud控制时间的3柄利器。
注二:在wiki里诚三的一篇文章中也讲过#alarm这个命令,不过我认为他讲的"-"的作用不准确,而且时间中应该不允许出现小数,所以#alarm -0.5是永远也不会触发的。
注三(新增):在721中去测试#alarm发现wiki里诚三的文章讲的是正确的。由于alarm命令在721中与另2个版本差异较大,下面专门举几个例子说明下。

不管什么版本中,#alarm都是trigger,时间就是它的Pattern。

在721中,Pattern相同的#alarm +@time,后建立的不会替代先建立的。

#alarm -0.5 {};#alarm -10;#alarm -30{}
时间中用到了-号,并且小时和分都未指定,分别是每0.5秒,每10秒,每30秒触发一次,不以连线时间触发,跟#alarm +类似,但是触发之后不会删除。后建立的会替代更新掉先建立的。意味着不停的输入#alarm -5 {commands},commands永远不会执行。

#alarm -1:05 {};#alarm -2:30 {}
这2个命令跟zmud555中一样,以连线时间为触发,只触发一次。

最后的总结就是721中alarm命令很矛盾很复杂,使用时请尤其小心。更多的差异请自行试验。


第八章 提高机器人稳定性和适用面

8.1 防止发呆

实例一:跳楼机器人做起来很简单,但是从塔上跳下来之后会busy 1.5秒左右.大部分时候1.5秒以后就可以继续跳楼了,但是由于网络的原因,有时候2秒都不能保证busy结束.
如果#wa 2500;enter;do 6 up;out固然比较保险,效率却很低.
2.5秒跳一次和1.5秒跳一次从效率上来说差别太大.
#tri {你已稳稳地站在地上。} {#t+ busy;#alarm +6 {enter;do 6 up;out};#wa 1500;enter;do 6 up;out}
#tri {你的动作还没有完成,不能移动。} {#t- busy;#wa 2000;enter;do 6 u;out} {busy}
这个trigger不仅能解决busy问题,同时还能解决up的时候被系统跘住的问题,机器人最多发呆6秒就能继续工作
在#alarm +6 {enter;do 6 up;out}未触发之前,再一次建立#alarm +6 {enter;do 6 up;out},这个时间触发器会被重置,触发器中的命令暂时不会执行,所以不用担心会出现多次跳楼的情况。

在侠客岛读石壁也可以用类似办法来防止机器人中断,同时设置好自动连线,除非服务器掉线超过10分钟才可能会从侠客岛上掉下来.
类似办法同样也可以用于打坐吐纳,钓鱼,读书,领悟等各种机器人中

防止发呆的一般做法:

步骤一: 一般一个机器人正常运转时,都会循环出现各种信息,可以将这些信息做成trigger,触发命令中加入#add idle 1
步骤二: #alias Testidle {#alarm +@time {#if (@idle>0) {#say 运行情况良好;#var idle 0} {#say 机器人已经中断;let it run};testidle}}
对@idle进行定时判断,如果@idle大于1,表示运行情况良好,变量归0;否则表示机器人中断,重新运转它

8.2 自动连线

非常简单但是实用的一个办法。

zmud555和721的alias列表里都有atconnect这个alias,atconnect中的命令是空的。你可以修改这个alias里面的命令,在连接到服务器时自动执行,用这个alias来输入帐号密码非常方便。
zmud462中虽然没有atconnect这个alias,但是你可以自己新建一个atconnect,功能和555 721版一样。

注:每当连接到服务器时,atconnect里面的命令都自动执行,不需要另外的trigger或者命令来执行它。所以它不是常规的alias,你在新建常规alias的时候,也不要取名为atconnect。

尽量为你的每个机器人都添加自动连线和防止发呆功能,在双保险的情况,你的机器人连续挂几天不是什么难事。

8.3 提高适用面

一个机器人可能只适用于某个id或者某个门派,需要更改很多变量才能适用于另外的id和门派。可是从大量的variables中寻找要改的变量不仅浪费时间,而且容易漏掉一些变量。如果你不是机器人的制作者,可能都不知道要怎么改。这个时候机器人的适用面就非常窄了,而且别人用起来也不容易,不能算是一个好用的机器人。

有3个命令可以用于解决这个问题,分别是#pick,#pr,#yesno

实例二:在我发布的555版领悟机器人中第一个按钮中的命令
n=1
#pr level "你要领悟或者练习到多少级"
//弹出一个对话框,提示你输入一个数字,这个数字被赋值给level,达到了修改领悟等级的目的,并且别人可以通过“你要领悟或者练习到多少级”这句话很清楚的知道要输入什么内容
#wh @n {#pick {p:添加要领悟或者练习的武功} {o:1} {添加基本功夫:#exe @action1
#exe @action2} {添加特殊功夫:#exe @action1
#exe @action6
#if %ismember(@skill,@tsskills)=0 {#exe @action3
#exe @action4
#exe @action5}} {*添加完毕:#var n 0}}
//这个命令要复杂一些了。#pick弹出一个选项框,可以提供很多选项来选择
//{p:添加要领悟或者练习的武功}为这个选项框设定一个名字或者称为"title"
//{o:1}表示这个选项框为单选框,去掉这个则默认为复选框
//{提示信息:命令}设置这个选项框的选项,当鼠标点击选择这个选项时,命令被执行
//{*添加完毕:#var n 0}}提示信息前面加入了*,表示这个选项为默认选项
//上面#pick总共设置了3个选项,只有当选择最后一个选项时,#while的循环中止,整个命令结束,否则反复弹出选项框,用来反复添加基本功夫和特殊功夫

实例三:如果你的机器人有自动连线功能,那么制作一个按钮来修改帐号密码等信息就很必要了
#button 0 {修改帐号} {#pr account.zhanghao "你的帐号";#pr account.mima "你的密码" "*"}
这里#pr account.mima的时候,多用了一个可选设置"*",当你在对话框中输入密码时显示****,也算是一个有趣的功能吧.

实例四:万安塔简化识别码的输入
#tri {你向鹿杖客打听有关『进塔』的消息。} {#pr answer "识别码";exert powerup;answer %upper(@answer);perform busy wushi}
#alias jinta {ask ke about 进塔}
在万安塔门口输入jinta,就自动弹出一个对话框询问你识别码,对照图片在对话框中输入小写的识别码,自动回答大写的识别码,同时powerup和 busy武士

#yesno "question" {yes-command} {no-command}
这个命令用来弹出一个对话框询问你一个问题,如果你点yes,那么yes-command被执行,否则no-command被执行

做机器人的时候尽量考虑到门派的差异以及帐号密码的不同,然后制作一些按钮来修改这些信息,不光自己在用不同id挂机时更加方便,别人也更容易使用你的机器人.


第九章 丰富你的机器人

本章主要介绍各种实用的小命令,让你的机器人变得更有意思

9.1 #beep #play

#beep 让zmud播放音乐,可以在菜单中找到sound进行设置,只支持wav格式
你可以下载一些wav格式的音乐或者干脆自己录制一个
任务完成之后播放一段轻松的音乐,或者遇到危险播放一个警告的音乐都是不错的选择

#play 支持wav、mid、avi格式,把你想要播放的音乐放到zmud目录下或者放到zmud的子文件夹中,然后在命令行或者trigger中用#play filename.wav命令就可以播放了.如果#play命令没有效果,可能是zmud没有找到该音乐文件,请参照下图修改




9.2 status bar

窗口最下面得一段空白的地方就是status bar,你可以在这里显示你最关心的内容,
这里给出1张截图,分别是我的胡一刀机器人和护镖机器人中状态条显示的内容




图中显示了任务计时,这个时间用#alarm每秒更新一次,完全同步显示出任务花费的时间

#st命令用来定义状态条

比如我的护镖机器人中是这样定义的:
#st {【任务:@address  伙计@huoji】【伙计位置编号@huojinum】【第@round轮:用时@time秒】【本次连线成功推车 @success/@total次】}

9.3 #cap

实例:#tri {【闲聊】} {#cap chat}
把所有的聊天信息抓到另外一个窗口单独显示出来,不用担心刷屏太快看不到聊天信息
当然你也可以把你感兴趣的任何信息都抓到另一个窗口显示出来。

9.4 #co #cw #hi

#co 改变最后一行显示信息的颜色
#cw 创造一个触发,只改变指定信息的颜色,该行中**内容的颜色不变
#hi 如果最后一行的颜色为暗色,则改变为亮色;如果为亮色,则改变为暗色

颜色的代码如下:
black   0
blue   1
green   2
cyan   3
red   4
magenta  5
brown   6
grey   7
yellow   14
white   15
bold   128

你可以直接用red,blue,yellow来指定颜色,也可以用代码来指定颜色
比如:#co red或者#co 4是一个意思

#cw 唐果 red,highlight,blink
//创造一个触发,将屏幕上唐果2个字全部用亮红显示,并且闪烁,这里使用了复合颜色

#show %ansi(green)欢迎使用%ansi("red,highlight,blink")糖果机器人!
//用到了%ansi(颜色代码),在一行中可以显示多种颜色

#LOOP 20 {#SHOWP %ansi(%if(%i\2=0,green,"blue,bold")).oOo};#SHOW
//#showp和#show类似,区别在于#showp不另起一行。最后用#show结尾,表示显示完毕,另起一行;命令中的"\"表示模运算,等同于%mod()
//这条命令显示的内容很有趣,有兴趣的不妨把它复制到你的命令行里看看,你可以用#showp和%ansi()来显示更多有趣的内容.

9.5 #mess

当我正在看网页的时候,我的遍历机器人没有找到盗宝人,可以用这个命令提醒我。我可以选择关闭机器人手动去迷宫杀盗宝人,也可以不管它,让机器人放弃这个任务。
你可以将#mess用在更多的地方,无论是提醒还是危险警告都不错。

9.6 #gag

当你在领悟或者读书的时候,刷屏太快,可以用#gag来屏蔽某些信息。需要注意的是,被屏蔽了的信息虽然看不到了,但是它还是存在的,并且机器人会通过这些信息来触发trigger,所以这个命令仅仅的作用就是让你看不到。

#tri {屏息凝神,一神守内,一神游外,意图双手各成方圆,却总是很难成功。} {#gag}
//在学左右互博时,这行字出现的太多,没有任何意思的刷屏,屏蔽掉!

9.7 #sc

当张三跑出来时,由于你的屏幕跳动太快,看不清张三找谁比武了,你可以用#cap,也可以用这个命令

#sc "张 三" 10
//显示最后10行包含张三的信息;如果去掉10,则显示所有包含张三的信息
//省去了你用滚动条到上面手动寻找的麻烦

9.8 #log

把你需要的某些信息保存到一个文本文件中,日后研究或者统计都可以

#log filename.txt
//开启log,接下来所有信息都会保存在filename.txt中
#log
//如果log已经开启,用这个命令关闭log
你可以通过反复的开启关闭来保存你感兴趣的内容。

9.9 #ig

你是否觉得同时关闭所有的trigger太麻烦,需要用#t-来关闭每个类.这时你可以用这个命令,当你需要打开时,再次输入#ig命令就可以了.

注意:用#ig来关闭触发,相当于你用鼠标点击zmud窗口右下角的**图标,并不会改变triggers的enable和disable状态.看下面的几个例子

#ig;#alarm +5 {#ig}
//这条命令的初衷是短暂的关闭5秒再打开,可惜#alarm +5是trigger,而所有的triggers都是关闭的,所以5秒后不会打开triggers
#ig;#wa 5000;#ig
//#wa好比泼出去的水,收不回来的.关闭5秒后能自动打开.同样你也可以用计时器来打开.

9.10 #stw

这个的用途跟定义status bar类似,当你觉得status bar太短不够用的时候你可以用这个.当然也有**用途.

#stw {hp;@qixue/@maxqixue  内力neili/@maxneli %cr 精神: @jingshen/@maxjingshen 食物food 饮水drink %cr 潜能pot  经验: @exp}
//如果你已经用trigger把相关信息保存到了上述变量中,这条命令会打开一个小窗口来显示你的hp有关信息
//%cr的作用是换行.

你也可以用%ansi()来选择你喜欢的颜色,例如
#stw {本次推车获得%ansi(red,high)@expgrain}
//你获得的经验需要用trigger保存到@expgrain中

#stw on和#stw off分别是打开status window窗口和关闭status window窗口

9.11 #tab

此命令用来定义一些快捷命令,比如
#tab "ask lin about job"
//不论什么时候,在命令行简单的输入一个a,然后按一下键盘上的tab键,ask lin about job就完整的出现在命令行中了

9.12 #menu

这个命令让你可以用鼠标发送命令,请看下面几个有趣的用法

#menu admire {chat* admire %lower(%selword)}
#menu praise {chat* praise %lower(%selword)}
#menu goodman {chat* goodman %lower(%selword)}
//当你把上述3条命令输入到你的zmud中之后,右键点击屏幕,你会看到弹出一个菜单,比平时多了3个选项,任意选择一个,括号里面的命令就发送出去了
//当你右键点击某个玩家的id,然后任意选择一个,你就会在闲聊频道对该玩家发出表情动作了.
//如果你点击的是空白地方,执行的命令等同于chat* admire/praise/goodman
//%selword意思是你选中的单词

这个用法也可以帮助你捡东西或者卖东西,但是请不要用这个命令来kill sb,不小心点错了概不负责.

9.13 #all

当你在一个窗口中输入#all {vote unchblk sb.},你的所有窗口都会发出vote unchblk sb.命令.

9.14 窗口名:{命令}

sghjjj:tell tangguo [@qixue]
//如果你的大米的窗口名是sghjjj,那么这个命令能让你的大米把他的气血值告诉你
//值得注意的,大米tell过来的信息中,@qixue的值是sghjjj窗口中变量qixue的值,这条命令可以让你和你的大米配合的更完美.
//相当于直接在sghjjj这个窗口中输入了冒号后面的命令

你可以用#name xxx 来更改窗口名字

9.15 #gauge(新增)

命令格式#gauge number "Title" @variable @maxvariable (表达式)

用途:将2个变量以图形对比的形式表现在一个浮动的条形框内

number:定义浮动条形框的序号
"Title":定义浮动条形框的标题
@variable和@maxvariable分别为你关心的2个变量,比如气血/气血最大值,任务已花费时间/任务总时间等等
(表达式)可以设定一个危险警告,比如 (@maxvariable/5),那么当@variable<(@maxvariable/5)时,用红色显示@variable所占百分比,否则用蓝色显示。

实例:护送任务总时间10分钟
接到任务时{#var time_left 600;#alarm -* {#add time_left -1};#gauge 1 剩余时间 @time_left 600 (60)}
//time_left初始化600秒,用一个每秒触发一次的trigger同步更新@time_left的值,创建一个浮动条形框显示任务剩余时间,当剩余时间小于1分钟时,浮动条形框的颜色变为红色
任务完成时{#untr -*;#gauge 1 off}
//任务完成后删除alarm类型的trigger并且关闭剩余时间显示



通过序号,你可以定义很多个这样的浮动条形框。你可以用下面的命令随时关闭打开某一个或者所有的浮动条形框。
#gauge 1 off    #gauge 1 on
关闭或者打开第一个浮动条形框
#gauge off      #gauge on
关闭或者打开所有的浮动条形框

这个有趣的命令也可以用来显示你的血量或者你正在领悟的技能,Have Fun!

注:类似以上一些实用小命令可能还有很多暂时想不起来,我会随时添加

到本章为止,zmud的大部分内容已经基本介绍完毕,如果你看到了这里,相信绝大多数机器人已经难不倒你了.


本来还有高级篇,不过我没找到,暂时没法帖,以后找到了再补充
MUD - MUD游戏 - 文字MUD - 武林MUD - 长期、稳定、高速、互助、活跃、更新的武侠MUD站点,一起MUD吧!

Archiver|武林MUD资料站 ( 鲁ICP备17038480号 本站关键词:mud 武林mud mud游戏 文字mud

GMT+8, 2019-11-22 18:59

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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