【梦话连篇】水阔鱼沉何处问——对机器人罢工说“不”
本帖最后由 hijacker 于 2013-2-28 10:44 PM 编辑不知道各位看官有没有这样的经历:晚上睡觉前依依不舍地wave 360度,然后挂好领悟机器人,gosleep(也许还顺带做了个成为大侠的美梦:),结果第二天起床一看:机器人因为某种原因罢工了,您的ID正在客店静静地看花开花落、云卷云舒呢!@#¥%……&*
也许笔者的机器人功力欠佳,以上惨案无数次地出现在笔者的生活中,令人倍感无奈。仔细总结,自己制作的机器人往往只考虑了理想情况,而没有考虑到各种意外因素,例如断线(这是俺机器人的第一大杀手啊,吐槽下北侠的服务器线路)、走路时踩到香蕉皮、路上被人guard、途中某个房间需要翻页吃掉了一个指令(例如岳王墓广场或人多时的达摩院二楼)、路上被NPC缠住(例如地痞、宝象、狼)、卖酒袋的NPC被杀死——总之,这个世界很精彩,这个世界很复杂……面对这么多意外因素,制作机器人的你会如何选择?是考虑所有可能的突发状况,还是听天由命、时不时地凑到显示器跟前去巡查一遍呢?
Considering…
北大侠客行MUD,中国最好的MUD 本帖最后由 hijacker 于 2013-2-28 10:46 PM 编辑
记得在某本书上看到过这样一句话:有两种方式构建软件设计:一种是把软件做得很简单以至于明显找不到缺陷;另一种是把它做得很复杂以至于找不到明显的缺陷——想来在MUD机器人的制作上也是如此。而MUD环境的复杂性,让我向着第二个方向思考。不亮在4楼说自动行走完破,我认为自动行走(以下简称GPS)并不等同于一个24小时工作的robot。为方便讨论,下文将忽略行走的细节,假设玩家拥有GPS或其他的能够精确行走到某一房间的手段。
首先需要明确的是,很多外力是我们无法避免的,如延迟、掉线、角色突然死亡等意外事件(这里不考虑断电,因为它涉及的问题就不仅仅是机器人了)。机器人要做的事情,就是尽可能地恢复被意外事件破坏的现场,或者在无法恢复现场的情况下,放弃某段任务以保证后续任务的顺利运行。
我做过的最多的任务是护镖,最熟悉的任务却是慕容玉玺任务(尽情地鄙视俺这只小菜吧)……就拿慕容举个例子吧。我们知道慕容任务的一般流程是:A接任务=>B走到任务指示的目的地=>C在目的地周围几格内走动(即“遍历”)找到叛徒=>D战斗得到玉玺=>E返回=>F交任务。情形一,假设我们在执行A步的过程中突然掉线,重新连线后你肯定会希望机器人检查是否接到了任务即A步是否成功——不成功则重新执行A接任务的动作来使被破坏的流程回到正轨(即“恢复现场”)——然后继续,事实上这个“恢复现场”的功能是很容易实现的:重新连线后打个”quest”或”jobquery”,然后机器人就能据此做出是否需要重新ask job的判断了。情形二,假设我们在执行D战斗这一步的时候突然掉线,重新连线后慕容叛徒很可能已经离开了你所在的房间,这时候我们无法像之前一样,简单地采取“不成功则重新执行D战斗”的策略,而是要退回C遍历找到叛徒,然后依次执行后面的步骤。以上两种情形,显然前者的工作方式更容易被机器人表达。那么,我们需要重新调整一下整个流程中步骤的划分:A2接任务=>B2走到任务指示的目的地=>C2遍历并战斗得到玉玺=>D2返回=>E2交任务。这样调整之后,在有GPS的情况下,无论在哪个步骤断线,机器人可以有效地进行校正,让角色的行为重新步入正规。
那万一我们在和叛徒的战斗过程中不幸中弹、光荣牺牲了呢?如果按照刚才的方法判断,显然机器人无法单纯地采取“C2不成功则重新执行C2”的策略,因为自鬼门关走了一遭后,复活后的位置已经发生了变化,此时应退回到B2步并依次执行后面的步骤。于是,我们再次对整个流程的步骤划分进行修正:A3接任务=>B3走到目的地、遍历并杀死叛徒得到玉玺=>C3返回慕容复处并交任务。这一次修改之后,整个过程被减化(不是“简化”,因为整个流程的复杂程度始终不变,只是划分方式发生了变化)成3步,无论中间哪一步出了问题而没有成功完成,机器人只需要重复这一个步骤即可恢复现场。至此,一个完整任务的流程就被我们划分为更“机器人”的几个步骤。我们来总结一下这些步骤的共同点:
1. 每个步骤之间有明确的界限,方便机器人判断当前进度,即隔离性。如A3和B3之间的界限是慕容复指示叛徒位置的那句话或者quest/jobquery列表中出现慕容任务的具体内容;B3和C3的界限是“你从慕容叛徒的尸体上搜出一块玉玺”这句提示;C3完成的标志自然是慕容复那里的奖励信息。这样也方便我们理清思路,分段编写机器人。
2. 每个步骤都具有“原子性”。原子,取其“不可分割”的特点,意即每个步骤一旦因意外而失败,就整个地重复该步骤,而不是从步骤的中间点开始执行——在机器人的意识中,每个步骤都是不可再分割的,要完成就整个完成,要重复就整个重复。
3. 每个步骤都具有恢复现场的功能。如前所述,只要简单地重复该步骤就能够保证机器人的持续运转,而不需要退回之前的某个步骤。
我觉得原子这个形容比较贴切,于是给上文中的“步骤”起了一个名字,叫“原子动作”,来强调每一个步骤的不可分割性。因为在我看来,即使你只想向西移动一步,也不能把即将发生的动作看成是输入一个”w”然后敲回车或者Execute(“w”)这么简单(如果你不想让自己的机器人有借口罢工的话),而是应该考虑一系列因素(其实主要还是掉线),然后把这个移动的指令”w”和相应的成功判断、失败判断整合到一起,打包成一个原子动作(比如封装成一个函数?),每次向w移动时都调用这个原子动作,以保证每次行动的成功,其他动作也是如此。如果我们的每个原子动作都对各种异常进行周全的考虑和处理,那么积土成山、积水成渊,你的整个机器人都会具有强大的容错能力,即使发生各种意外,它也能顽强地跑着,不会罢工。
有一种情况我还是提一下,就是像慕容任务过程中断线10分钟依旧无法连接成功导致自动 quit、叛徒消失(事实是这样的吧?其实我不太确定NPC是否会消失)这种,整个流程被彻底破坏、完全无法恢复的,就只能重新初始化后从头再来了,没有其他办法——机器人不是万能的,但我始终(盲目乐观地?)坚信,一个优秀的机器人(哪怕我现在还做不出来)应该有着强大的容错能力、让使用者能够放心离开,否则,再强大的机器人,缺少了“抗逆性”(没听说过这个词的请百度,不解释了),也只能是一只好看的花瓶,中看不中用。
填坑行动先到这里,等有新的想法时再来填4楼:-) 再占一楼 自动行走完破 一直懒得动笔,今晚心血来潮写了一段。如果没有新的想法,可能就填到这个程度了。
顶起来,欢迎拍砖yct43.
页:
[1]