逆转就是将路径倒过来,并且每个方向都替换成逆方向.
#var fangxiang {n|e|nw|ne|nu|nd|eu|ed|u|enter|s|w|se|sw|sd|su|wd|wu|d|out|open door}
#var fangxiangb {s|w|se|sw|sd|su|wd|wu|d|out|n|e|nw|ne|nu|nd|eu|ed|u|enter|open door}
//这2个变量只保存了常规的可逆的方向,如有其它可逆的方向都可以添加进去,只需要注意2个变量对应的方向正好相反就可以了
//不属于上述2个变量中的方向,默认为不可逆.路径不可逆时只能继续遍历到终点
#alias reverse2 {#if (@step>0) {#if %ismember(%item(@path,@step),@fangxiang) {#var path2 %additem(%item(@fangxiangb,%ismember(%item(@path,@step),@fangxiang)),@path2);#add step -1;reverse2} {#say 路径不可逆}} {#var path @path2;#say 路径逆转完毕}}
//逆转路径的alias写起来很简单,将你要逆转的路径保存在@path中,从@path的最后一个item开始依次取出每个方向,如果可逆则获得反方向添加到@path2中,否则"#say 路径不可逆"并且终止逆转
#alias reverse {#var path2 {},#var step %numitems(@path),reverse2}
//初始化变量@path2和@step,然后启动reverse2开始逆转
上面2个alias就完成了逆转,逆转的对象是@path.
使用逆转的方法:
要逆转某个路径@abc,输入命令#var path @abc;reverse.如果路径可逆,则将逆转后的路径保存在@path中并且输出信息"路径逆转完毕";否则输出信息"路径不可逆"并且@path中的内容不变.你可以分别用"路径逆转完毕"和"路径不可逆"制作trigger继续下一步行动.
简化就是判断路径中相邻的2个方向是否互为可逆,如果是则同时删除.
实例:
#var xyscq {n|n|w|w|w|e|e|n|s|s|e|w|n|e|n|n|n|s|s|s|e|n|w|e|s|s|n|e|s|e|s|n|w|nw|se|w|e|s|e|w|w|e|s|n|n|n|e|n|s|s|n|e|n|s|s|n|e|w|w|w|n|se|e|w|nw|w|e|e|u|d|w|n|w|u|d|e|e|u|e|w|u|d|d|w|n|n|n|nw|n|s|se|n|n|n|n|过河|n|e|w|w|u|d|e|n|n|w|nu|sd|w|nu|sd|e|e|ne|ne|n|s|sw|sw|n|n|e|w|n|n|n|n|w|e|n|w|e|n|w|e|e|w|n|e|n|s|e|n|s|e|w|w|w|n|e|w|n|e|w|w|e|n|s|s|s|w|n|s|s|n|w|s|n|n|s|w|w|w|w|e|e|e|e|e|e}
//这个变量中保存了从林震南那里一直到襄阳史春秋附近的遍历路径,沿途各个分叉口全都遍历到了
搜寻伙计可以遍历这个路径,但是返回仍然用这个路径则会浪费很多时间,需要写一个alias获得从起点到终点的最短路径
#alias jianhua2 {#if (@step>=%numitems(@path)) {#say 路径简化完毕} {#var num1 %ismember(%item(@path,@step),@fangxiang);#math step2 @step+1;#var num2 %ismember(%item(@path,@step2),@fangxiangb);#if (@num1=0) {#add step 1;jianhua2} {#if (@num1=@num2) {#delnitem path @step;#delnitem path @step;#add step -1;jianhua2} {#add step 1;jianhua2}}}}
#alias jianhua {#var step 1;jianhua2}
//这2个alias就完成了路径@path的简化,简化结束后输出信息"路径简化完毕"
#var path @xyscq;jianhua
//将@xyscq赋值给@path,然后简化它
#say @path
//显示为n|n|e|e|n|n|n|n|n|n|n|n|n|过河|n|n|n|n|n|n|n|n|n|n|n|n,得到从林震南那里到襄阳城中心的最短路径
注二:如果要获得从起点到当前位置再到终点的最短路径,只需要对上述方法进行修改即可.一个比较简单的方法就是:先将路径@path中当前位置的方向替换成myaddress,并且将该方向保存到@myaddress中,由于"myaddress"不可逆,因此简化的时候不会删除myaddress.简化结束后将路径@path中的myaddress还原或者新建一个alias:#alias myaddress {@myaddress}都可以。
注三:护镖任务的路径,路径都很简单,方向都很规范,用逆转和简化的时候不需要考虑可逆不可逆的问题。胡一刀的路径就要复杂些,很多特殊的方向和不可逆的方向,还有很多有时候可逆有时候不可逆的方向,在使用逆转和简化时就需要特别注意了,一般主要用于洛阳北京襄阳丐帮扬州这类路径较长并且方向规范的区域;如果硬要用于胡一刀的全部路径,也不是不可以,只是制作路径和定义可逆方向的时候复杂很多罢了。
注四:逆转和简化只是2个将路径"变形"的方法,每个人写机器人的方法都不一样,请参考使用。对路径的"变形"使用不仅仅只有这2个方法,如有需要,完全可以自己写一些其它的alias来使用路径。用list类型变量来制作遍历的优点就在这里,一个路径拿来,想怎么玩就怎么玩,这是path办不到的,只是要求能熟练的应用和list类型变量和嵌套罢了。
13.2 胡一刀和护镖全自动
对于这种复杂的大型机器人,需要克服的障碍很多,运行过程中各种意外会经常出现,想一次性达到完美是不可能的。写机器人之前,不妨先大体考虑下主要会出现哪些问题,哪些是容易解决的,哪些是比较困难的,哪些是不可能解决的,该放弃的就适当放弃,比较麻烦的地方以后慢慢完善,毕竟最终的目的是要全自动。
搜索盗宝人
可以用慢速行走,第11章中的方法就可以完成。用这个方法时建议set brief 2,"这里明显的出口是 south 和 out。"类似这样的信息会出现在盗宝人的后面,用这些信息作trigger可以正确判断是继续下一步还是停下杀盗宝人。杀完之后的采用顺向返回,为了提高效率,返回时最好简化路径。不必追求完美的简化获得最短路径,非标准的方向都默认为不可逆,只简化掉标准的方向即可。相比完美的简化,仅仅就是多浪费0-4秒钟在返回的路上,但是实现起来却容易得多。
也可以用快速行走,优点就是搜索盗宝人的速度更快。由于主id用快速行走来搜索,肯定会走过头的,路过npc的时候也会导致盗宝人叫杀,盗宝人叫杀之后就会乱跑,因此推荐用大米快速搜索。快速搜索盗宝人需要通过数房间名出现的次数或者数"这里明显的出口是 south 和 out。"这类信息出现的次数得到盗宝人在路径中位置。如果坐船杀挡路npc或者开门也是路径中的方向的话,数数的时候也要作调整,一定要确保最后得到的结果是正确的。主id通过盗宝人的位置快速行走到盗宝人那里就可以了。这种方法也有缺点,被系统跘住或者被主动叫杀的路人甲纠缠住这类情况总是会发生的,如果是大米退出重新搜索就可以了;如果是主id,可以让大米再搜索一次,同时搜索自己和盗宝人。
对于第十一章中给出的快速行走也可以稍作修改
#alias bianli {#if (@step<=@steps) {#if %ismember(@step,@busy) {#wa @time;halt;%item(@area,@step);#add step 1;bianli} {{#if (%mod(@step,@bushu)=0) {#wa @wait;tell @zhanghao 继续快速行走} {%item(@area,@step);#add step 1;bianli}}}}
#tri {你告诉*:继续快速行走} {%item(@area,@step);#add step 1;bianli}
//对%mod(@step,@bushu)=0的情况作了修改,此时嵌套暂时结束并且tell自己一句话,用这句话作触发继续嵌套,可以完全避免网络lag时命令堆积过多服务器拒绝执行的情况。
有些迷宫也是可以搜索的,比如大沙漠
#var shamo {w|heshui|w|heshui|w|heshui|s|heshui|w|heshui|w|heshui|w|heshui|s|heshui|w|heshui|w|heshui|w|heshui|w|heshui|w|heshui|s|heshui|w|heshui|w|heshui}
#alias heshui {#10 drink jiudai}
如果遍历星宿没有找到盗宝人,可以用慢速行走遍历大沙漠,酒袋里装满水去沙漠起点就可以开始遍历了,每个"heshui"方向都有busy。类似这些地方,初次制作机器人的时候最好直接放弃,以后再慢慢修改添加完善。
护镖
这个就比较简单了。由于路径都很简单,只包含标准方向,可以直接从林震南那里遍历搜索店铺伙计,也可以先将镖车推到伙计附近的某个固定地点,如果沿途没有看到店铺伙计,再搜索伙计附近的小型区域。搜索结束后将路径中伙计后面的方向全部删除,剩余部分简化就得到从镖车到伙计的最短路径,推过去就可以了。无论是大米搜索还是主id搜索,也无论是大米贴身跟随还是呆在家里,实现起来都没有难度。
逆转和简化在护镖机器人中用起来很方便,没有什么需要注意的地方。并且路径也不用做成封闭式的(即从起点出发溜一圈回到起点),可以自己写一个返回alias,从当前位置依次往前执行每个方向的反方向直到回到起点。无论在什么地方,只要没有迷路(此时@step的值就是当前所处位置在路径中的编号),将@step后面的方向删除,逆转简化顺序快速行走就返回了。
推车子的时候使用的路径也是类似{e|e|e|n|n|ne}这样的list变量,定义2个变量
#var fangxiang {n|e|nw|ne|nu|nd|eu|ed|u|enter|s|w|se|sw|sd|su|wd|wu|d|out}
#var fangxiang2 {north|east|northwest|northeast|northup|northdown|eastup|eastdown|up|enter|south|west|southeast|southwest|southdown|southup|westdown|westup|down|out}
用gan che to %item(@fangxiang2,%ismember(%item(@path,@step),@fangxiang))命令推车就可以了
解决乱入或者迷路的万能办法
无论是护镖中镖车被劫匪移位,还是胡一刀中在杀盗宝人的时候盗宝人到处乱跑,或者是其他的意外情况,都导致一个结果,就是@step的值不再是你在路径中的位置,将你所在区域告诉你的大米,让他来搜索你,重新更正@step的值或者直接更正路径都可以。
要求你有从林震南到店铺伙计那里的完整路径,沿途每个分岔口都要覆盖到,以确保乱入3步以内能被大米搜索到。
如果乱入到沙漠黑店ct上面的赏月台这样的地方,这些位置可能不在路径中,大米是搜索不到的,寻求大米帮助之前先判断下地名就可以了,如果是这类地方,推到路径中之后再向大米发出求助信息。
对于乱入,一般只是移位1-2步,比较简单,下章再介绍2个解决办法供参考。
注五:大概想到的困难也就这些,如果大家还有什么困难不能解决可以回帖说明,如果我有解决的办法会修改补充进来。
注六:建议大家在制作机器人之前不要想将所有困难一网打尽,一次性考虑所有情况只会使你做不下去,你的机器人就夭折了。对于一些细小的地方,该放弃的就放弃掉。比如为了鳌拜下面的密室这一个房间专门写很多trigger进去搜索是没有必要的。全自动做任务肯定没有半自动手动操作的成功率高,但是机器人胜在反应速度比人快,胜在不知疲倦,这些优点也足以忽视它的不足了。先保证机器人的效率和稳定,再慢慢提高机器人完成任务的成功率,对于麻烦的复杂的情况建议暂时做放弃处理,大不了退出重新连线开始下一个任务嘛!
下一章介绍多个路径的连续遍历方法,另外提供2个解决乱入的办法供大家参考!