|
楼主 |
发表于 2013-1-8 01:15:26
|
显示全部楼层
本帖最后由 hijacker 于 2013-1-8 11:06 AM 编辑
机器人的基石——浅谈触发器(下)
了解了触发器的基本工作原理,我们可以制作自己的触发器了,来享受DIY的乐趣吧!怎样DIY触发器?先来看一个简单的例子。以下是一个特别的吐纳机器人
#tri {((*))} {#if %pos("你吐纳完毕",%1) {exert regenerate; tuna 100};#if %pos("你现在精不足",%1) {sleep};#if %pos("你一觉醒来",%1) {tuna 100};#if %pos("你刚在三分钟内睡过一觉",%1) {#wa 3000;exert regenerate;tuna 100}} {} 519
为了通俗,我尽量选择用ZScript来描述问题,MUSHClient和Tintin++的原理是相同的。注意到了吗?在zMUD看来,以上只是一个触发器,但我们却用它完成了四个触发器的任务:用(*)把每一行的所有内容捕获到%1后,剩下的匹配规则完全是由我们自己制定的(这里主要用到了pos函数)。有人会说,这样折腾多麻烦啊,一点都不如正常方法容易!的确,乍一看上去,这完全有点自找麻烦的味道在里面。但我要说的事,这种方法给了我们一样东西,那就是“自由”(对对对,就是那个举着火炬的女神)!在zMUD中这种自由可能不够凸显,我们把目光转向可以使用脚本语言的客户端(下文对zMUDer可能没什么意义,抱歉),比如MUSHClient。首先,我们把DIY触发器的所有文本及其对应动作、选项等放入一个表(table)中——表中的每一项相当于一个被模拟出来的触发器内容,然后像zMUD那样用(*)捕获一行,再把这行和表中的每行进行比对,比对成功则执行对应动作。对应于zMUD里的#tri,我们也可以在MC里写一个trigger函数,示例如下:
function trigger(name, match, script, temp, args, keep, priority, color)
table.insert(triggers, {
["name"] = name, --触发器名字
["match"] = match, --触发器文本
["script"] = script, --匹配成功后的动作,以函数方式传递
["temp"] = temp, --是否是临时触发
["args"] = args, --前面的script函数的各种参数
["priority"] = priority, --优先级,数字类型
["color"] = color, --是否是颜色触发,预留项,还没有想好怎样实现
["keep"] = keep, --相当于MC原装触发器中的“保持有效性”
})
end
当我们用捕获整行信息时,就可以把这行信息和triggers表里的每项进行比对了,比对的框架大约是(会有人对这个感兴趣吗?)
for i, v in pairs(triggers) do --triggers表事先要根据优先级排好顺序
if line, v.match 匹配成功 then
执行v.script(args)
if v.temp表明本触发是临时触发 then
删除该触发
end
if 不保持有效性 then
break --不继续对比
end
end
end
这样一来,我们就几乎可以用纯lua模拟一系列MC触发器,我想TinTin++等其他支持脚本语言的客户端应该也能实现类似的功能(未验证)。好咧!关于DIY触发器的表演就先到这里,不得不说,代码真的是很能占字数的:-)
不知道各位看官此时有没有紧锁眉头满脸茫然,我且硬着头皮继续说下去。这样做到底有何意义?如前所述,它给了我们自己制定规则的自由。这么麻烦的自由到底有何价值?试想,它帮助我们在编写机器人时基本脱离了MC、TT++等客户端制定的大部分规则,那我们是不是可以用同一套脚本,既可以运行在MC上,又可以只进行少量的修改后直接运行在TT++上呢?在我的设想中,这应该是可以实现的(未验证,不然怎么叫“梦话连篇”呢,:-),至于不支持脚本语言的zMUD 4.62,我大胆猜测它可以通过DDE实现与脚本语言的交互,虽然我还不了解DDE是什么:-) 我梦想着未来会不会有这么一天——发在技术版的机器人再也不用区分zMUD/MUSHClient/TinTin++/其他...那将是一件多么cool的事! |
|