文字MUD游戏论坛-天下泥潭群英会-水泊梁山  

返回   文字MUD游戏论坛-天下泥潭群英会-水泊梁山 > 西游之旅 > 『 西游记2000 - 苏州站 』

『 西游记2000 - 苏州站 』
这里西游记2000苏州站的玩家聊天交流的地方。欢迎来自苏州站的朋友。

 
 
LinkBack 主题工具 主题评分 显示模式
旧 2005-03-09   #1
中级会员
级别:4 | 在线时长:50小时 | 升级还需:25小时
 
dragonstrike 的头像
 
注册: 05年02月16日
帖子: 73
声望力: 21
声望: 10 dragonstrike 闻道则喜
现金:97两梁山币
资产:323两梁山币
致谢数: 0
获感谢文章数:0
获会员感谢数:0
自动全解迷机器人 (下)

第三章 任务选择机制的实现

为了实现自动解谜,我们首先考虑机器人的工作流程。
我们可以知道,选择这一环节至关重要,它就是整个自动解谜系统的大脑。
下面我们来初步实现选择这一功能。
首先,这个流程需要一个起点,在图中“问谜”这一步引起了Quest.db的更新,
从而引发后续的整个过程,相应地,我们从游戏里也要找到这个起点。
我选择的是命令"quests"。
当下命令quests后,会显示当前需要完成的七项任务。我们通过Trigger来获取这些任务,
并将数据传送到Quest.db中。数据库中有个命令#LoadDB,这个命令用于加载一个数据库。
如果这个数据库还没有加载到内存,就从文件中读取并加载;如果这个数据库已经被加载了,
就将它作为当前的数据库激活,那么后面的数据库操作都是在这个数据库中执行。
我们用#LoadDB
命令把当前的数据库置为Quest.db,然后输入"quests"指令。接下去,
下面的Trigger会自动更新数据库内容。

#TR {^????食物:(%x)}
{food=%1;0.Name=@food;0.Nodo=@red}
#TR {^????送物:(%x) (%x)}
{yin=%1;thing=%2;1.Name=@yin;1.Nodo=@cyan}
#TR {^????拜贤:(%x)}
{baixian=%1;2.Name=%1;2.Nodo=@green}
#TR {^????灭妖:(%x)}
{hu=%1;3.Name=@hu;3.Nodo=@yellow}
#TR {^????武器:(%x)}
{weapon=%1;4.Name=@weapon;4.Nodo=@blue}
#TR {^????盔甲:(%x)}
{armor=%1;5.Name=@armor;5.Nodo=@pink}
#TR {^????募捐:(%x)}
{lan=%1;6.Name=@lan;6.Nodo=@white}

其中诸如0.Name之类的变量代表数据库中编号为0的记录的Name字段。
而red、cyan、green等变量是我在Trigger里用来对某个任务未完成次数记数的,
每完成一个任务,对应的任务的记数置成零,其他任务记数加一。
那么,这个数字越大的,就代表越久没有完成。

然后,根据判断Cloud字段的值。
#TR {^????你的身上徐徐飘浮起一小团(%x)祥云。}
{colorlist=%1;
0.Cloud=%pos( 红, @colorlist);
1.Cloud=%pos( 青, @colorlist);
2.Cloud=%pos( 绿, @colorlist);
3.Cloud=%pos( 黄, @colorlist);
4.Cloud=%pos( 蓝, @colorlist);
5.Cloud=%pos( 粉, @colorlist);
6.Cloud=%pos( 白, @colorlist)
}

#TR {^????慢慢地一小团(%x)色祥云在你的身边升起。}
{colorlist=%1;
0.Cloud=%pos( 红, @colorlist);
1.Cloud=%pos( 青, @colorlist);
2.Cloud=%pos( 绿, @colorlist);
3.Cloud=%pos( 黄, @colorlist);
4.Cloud=%pos( 蓝, @colorlist);
5.Cloud=%pos( 粉, @colorlist);
6.Cloud=%pos( 白, @colorlist)
}

这个时候,Quest.db的数据已经全部被更新,我们可以通过下面的方法来选择任务:
1、在数据库Quest.db中建立一张视图,取名为order。order视图按照{Cloud|Nodo}排序,
也就是排序优先级先Cloud,再Nodo。
2、下命令#View,将在Zmud中显示这张视图,排在第一行的就是我们所选取要执行的命令。
3、用Trigger得到该命令。

图例如下
#View order {Cloud|Nodo}
#View
0 食物 鹫肉 - 20
2 拜贤 王孙 - 5
1 送物 孙三叔 - 4
6 募捐 雕木斜靠椅 - 3
5 盔甲 王八甲 - 1
3 灭妖 笑波儿天 - 0
4 武器 月牙弯刀 X 2

(显示"-"代表没有云彩,"X"代表有云彩)

然后,我取得下面要做的任务名为“鹫肉”,将当前数据库切换为Record.db,
用#Query命令对该任务进行查询,获得应该执行的命令。
(关于查询请参考帮助文件,这里不作赘述。)

这样,一个简单的自动解谜机器人的框架搭好了。
但是这样的模型离投入使用的成品还相差太远,需要我们一步步加以优化和调整。
最重要的还是提高“选择”的正确性,因为任务的选择直接关系到奖励的高低即Trigger的效率。

第四章 解谜技巧的应用
为了提高解谜所获得的奖励,我们要合理选择需要完成的任务,
并且将它与Trigger 的可实现性结合起来,也就是说,
判断的条件必须是可以通过Trigger 实现的,否则,
再完美的技巧也无法应用在我们的自动解谜机器人中。
首先,我们假设机器人运行在一种理想状态之下,所有的谜都是可以完成的。
那么我们将遇到下面两种情况:
一、云彩数目小于七朵。这时,下一个要执行的任务应该是没有对应的云彩的那项。
我们知道,解谜的奖励和云彩数目关系密切,云彩越多,获得奖励越多,
机器人效率也越 高。因此,任务的选择首先必须符合倾向云彩增多的原则。
例如:你的身上有青绿黄蓝粉白六彩祥云,那我们可以通过触发器判断得知缺少红色云彩,
即下一个任务应该做猪八戒的食物。做完食物这一项,就可以将云彩累积到最大数目。
二、云彩达到最大数,即七彩祥云。这种情况下我们应
该遵循FDFD(First Done First Do即最先完成最早执行)原则。
让我们先来看看上一章提到的Nodo记数,它的机理如下:
设置七个变量red、cyan、green、yellow、blue、pink、white
分别对应该种云彩对应的任务记数。当完成某项任务,则将 相应变量置零,
其他变量加一。例如:

#Trigger {^????陈光蕊对你说道:多谢这位}
{quest_type=拜贤;green=0;#add cyan 1;#add blue 1;
#add yellow 1;#add red 1;#add white 1;#add pink 1}

这样我们可以通过这七个变量的值了解到某种类型的任务有多久没有完成。
因为云彩的存在是有时限的,自它产生以来,经历8次记数,也就是变量值为9的时候,
这朵云彩就消失了。
所以我们应该优先执行记数大的任务,以保证云彩维持在七彩。
上面提出的两种原则已经在我们的模型中采用了,即按照“Cloud|Nodo”的次序进行排序,
先考虑是否有云,然后考虑做最久未做的任务。但是,在实际解谜中,我们并不可
能完成所有的任务,一定会遇到有些谜无法完成。
所以我们在数据库Record和Quest中引入一个新的字段:CanDo。
这个字段为一,表示该任务可以完成,这个字段为零,则说明是无法完成的。
随着Player的成长,可以手动的对这个字段进行修改。
比如Player早期很难完成一些灭妖以及菩提祖师的拜贤、羊脂玉净瓶等任务,
到了后期,就可以调整为可以执行。
此外,我们对何时清谜做一个考虑。如果因为某些任务无法完成,
只能保持在较少数目云彩下解谜,奖励会降低;
而清谜会造成两个损失,一是随机减少一朵云,二是时间上的等待,
但清谜之后可以抛开那些挡路的任务,为七彩云创造条件。有得必有失,
如何选择清谜时机呢?根据我的解谜经验,六彩以下的任务是不值得做的。
我们可以判断,如果根据排序,最优先的两个任务无法完成,就可以去清谜了。
最后,我们再来考虑解谜任务的权重问题。各个任务的奖励是不同的,
在相同云彩数目下,有的任务比如兵器中的各种法宝和龙子兵器、
募捐中的龙珠等奖励高,有的任务奖
励低。这就牵涉到一个对任务赋以权值的问题。权值对两种情况造成影响:
一是在正常的要清谜的情况下如果有权值
很高的任务未做,可以考虑先做这个任务再清谜;二是当云彩少于七彩的时候,
考虑在没有其他损失的情况下,将权值高的任务放到云彩多的时候做,
以获得更高奖励。权值的设定可以不必在数据库中增加字段,将它与CanDo 字段合并,
CanDo为零,代表无法完成任务,否则表示该任务权重。
好了,经过这样的补充,我们的自动解谜机器人可以算是完成了,
首先具有可执行性,其次也满足了对高效率的要求。
当然,另外还有一些技巧因为很难在机器人中实现,我
们就不在这里赘述了。

第五章 完善与展望(结束篇)

经过前面四篇文章的讨论,我们已经得到了一个可以用的自动解迷机器人,
它包含了一个容纳所有任务的数据库,以及一个用来处理当前任务选择的数据库,
可以实现自动选
择当前任务,自动完成解迷任务的功能。当然还是比较粗糙的,
在运行过程中我们可能会遇到许多非理想状况,干扰机器人的运作,
另外,注意一些细节也可以提高效率。
首先我们注意解迷的等待问题,因为用机器人解迷,动作要比手动迅速的多,
所以从接迷到完成通常只要很短的时间,就需要等待,虽然这段时间一般只有1、2分钟,
但累积起来也不是一个小数目,所以我们要采取的策略是在每完成
一个谜之后立即询问该类型的任务。比如做猪八戒的食物,
把食物给猪以后,去皇宫领赏,然后再ask zhu about food。
由于选择的任务的一般趋势是各种类型任务轮流完成,所以在你完成其他任务的时候,
也度过了等待的时间。在我的解谜机器人里是这样实现的:
设定七个alias分别对应七种任务如askzhu, askchen, askyin等等,
在完成任务的时候有七句
触发如:
#trigger {^???猪八戒对你说道:多谢*} {type=zhu}
然后从皇宫领赏出来,执行alias ask@type就可以询问相
应的任务了。
其次,对于非固定位置的任务,比如送物,灭妖的NPC,要有自动寻找的手段。
这个利用路径是很合适的,例如:得到任务送物:街头小商人--黄金,
我们从数据库中得到方位在宝象,定义一个alias search如下:
#alias search
{
#untrigger {@findname};
findname=%-1;
#tr {@findname}
{#cw red;find=1;#untrigger {@findname}}
}
使用search @yin(yin这个变量的内容就是“街头小商人”)
就生成了一个触发,当#slow .baoxiang沿路径行走的时候,
遇到街头小商人就自动停下来,配合自动给物品的trigger就完成了这个任务。
另外,一个特定任务可能有多个选择方案,在手动解迷过程里,
如果遇到可以在多处完成的任务,我们可以自由选择,
即使一个地方没有,还可以去其他地方尝试。为了模拟手动解迷以提高任务的完成率,
我们也可以加入完成任务的多种方法。因为todo字段是一个memo变量,
我们可以输入很多内容。所以我们增加一个字段,类型为整数,
记录todo中的方法数量,然后依次执行。具体如何实现,请大家思考。
除这些以外,我们还有很多细节要考虑,比如PK(//grin),
比如小小怪的拦路,再比如@#%&^@*$#。这些问题就仁者见仁,智者见智了,
需要技术与经验的结合。不过我的原则是安全稳定第一,
处理问题的方法要简单,这个原则放在机器人制作具体的讲就是宁用alias,
少用trigger。这样说可能有失偏颇,但alias的执行是可以不考虑网速的,
而trigger往往受网速的限制。上次看到一个捡舍利子的机器人,
几乎所有动作都用trigger触发,有些明明可以
用一个alias解决的,也被拆分成了好几句trigger,害处就是第一容易被破坏,
第二机器负担太重,判断触发是相当占用时间的(当然如果你已经用上P4了,当我没说过)。
随着Zmud日益功能强大,我们可以实现的机器人也会越来越多,也会越来越完美。
目前我最看好的是automap,这个功能其实在Zmud 4.62里就有了,
automap结合trigger(其实也是一种形式的数据库结合trigger,因为
automap实际上是一个储存房间记录的数据库)应该会非常强大的。
但我看了很多介绍文章,也从zuggsoft 的网站上下载了资料,就是没有办法搞定,
没有办法正常做语法分析,区别一个房间的名字、描述与出口,
另外绘制地图的时候提供的方向也少了点,只有普通的
south,north,southeast,up,down之类。不知道有哪位已经搞定automap
的,希望指点一下。
好了,我终于结束了婆婆妈妈的废话,最后希望mudfan所有朋友
好运,玩得开心。
dragonstrike 当前离线  
回复时引用此帖

 

添加到书签


发帖规则
不可以发表主师
不可以回复帖子
不可以上传附件
不可以编辑自己的帖子

论坛启用 vB 代码
论坛启用 表情图标
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用



所有时间均为格林尼治时间 +9, 现在的时间是 08:06.


Powered by SPLS
版权所有 2001-2023 水泊梁山
皖ICP备05012024号

站长 fengyue

Content Relevant URLs by vBSEO 3.6.1