jarlyyn 发表于 2022-6-24 17:16:20

一步一步在北侠做机器人之 Ask篇-学会提问的艺术

本帖最后由 jarlyyn 于 2022-6-24 05:21 PM 编辑

前言:ask这块,很基础,但又能体会出 单纯触发条件发射 和分析处理的做机器的区别,就单独做一个篇短文
相信每一个北侠玩家都对ask这个命令映像深刻,毕竟这是一个从新人村 ask you about 闯荡江湖就一直伴随玩家的命令。这个命令是北侠很多任务的起点,所以可以说做机器人第一步往往就是处理ask信息。

北侠的NPC嗓门都比较大,回答问题时会让房间里的人都听到,这样机器没做好容易被别人的机器干捞。这种时候,最简单的方法就是做个多行触发,简单粗暴但有效。
但,ask的触发和响应,到底怎么做比较好呢?

我们能不能针对ask做通用的触发?

我们能不能记录下所有NPC对我们的回答,比如下图呢?



Mud是wiz规划好给人类玩家玩的,所以,最正经的机器人写法就是模拟人类玩家的反应,这样最不容易被wiz的更新干扰

要回答这个问题,我们先要分析下,什么是ask。

我们在丽春院ask命令后,游戏里会发生这些事:

1.向游戏发送
ask wei chunfang about 你真漂亮2.游戏中出现
你向韦春芳打听有关『你真漂亮』的消息。
这句话
3.游戏中出现
韦春芳说道:嗯....这我可不清楚,你最好问问别人吧。
这个响应

普通我那家会在看见 “你向韦春芳打听有关『你真漂亮』的消息。”后,寻找之后的一句或多句回答,这就是我们想要的答案。


好,那我们的机器应该怎么做呢?


首先,找一个变量,储存最后一次ask的内容和ask后的所有回复


App.Core.Ask={}
    App.Core.Ask.LastNPC=""
    App.Core.Ask.LastQuestion=""
    App.Data.Ask={}
    App.Core.Ask.MaxReply=10
其次,写一个ask命令,把最后一次ask的npc和问题记录下来
    App.Core.AskQuestion=function(npc,question){
      App.Core.Ask.LastNPC=npc
      App.Core.Ask.LastQuestion=question
      App.Send("ask "+npc+" about "+question)
    }接着,做一个触发,记录你向NPC题目的内容,表示紧跟在后面是NPC对你的回复
^你向(.{1,10})打听有关『(.*)』的消息。$当然,还有响应的代码
    App.Core.Ask.OnAsk=function(name, output, wildcards){
      App.Data.Ask.Replies=[]
      App.Data.Ask.Lines=[]
      App.Data.Ask.Time=Now()
      App.Core.Ask.LastNPC=""
      App.Core.Ask.LastQuestion=""
      App.Data.Ask.NPC=wildcards
      App.Data.Ask.Question=wildcards
      world.EnableTriggerGroup("core.ask.reply",true)
    }在代码里打开了core.ask.reply这个组,开始记录信息
当然,还要做个问的太快重问的触发
^你说话太快,对方听不懂,慢点说吧。$响应代码是
    App.Core.Ask.RetryAsk=function(){
      if (App.Core.Ask.LastNPC && App.Core.Ask.LastQuestion){
            App.Send("ask "+App.Core.Ask.LastNPC+" about "+App.Core.Ask.LastQuestion)
      }
    }如果没重问,那太棒了,开始记录回答了。我们应该把NPC回答的所有内容都记录下来。当然,有个限制,就加10个限制吧
加个触发
^(.*)$优先度要高点,别被别的触发拦截了

对应代码是

    App.Core.Ask.OnReply=function(name, output, wildcards){
      if (App.Data.Ask.Replies.length>=App.Core.Ask.MaxReply){
            world.EnableTriggerGroup("core.ask.reply",false)
      }else{
            App.Data.Ask.Replies.push(output)
            App.Data.Ask.Lines.push(JSON.parse(DumpOutput(1)))
      }
      App.Raise("core.reply")
      App.RaiseStateEvent("core.reply")
    }如果超过长度,就关触发组,不然把回复推到App.Data.Ask.Replies数组里。App.Data.Ask.Lines里放的是带样式信息,以防止需要判断回答里的色彩


App.Raise("core.reply")和App.RaiseStateEvent("core.reply")是发出事件,调用处理代码。这里也可以放类似钩子函数的东西,也可以放直接处理的函数



以我WDJ新人任务为例,大概就是这样一个代码逻辑
      switch (output.Words.Text) {
            case "说道:「你去提水浇菜地。":
            case "说道:「我不是给过你任务了吗?提水浇菜地,快去!":
                App.Quest.WDJ.Type = "jiaoshui"
                break
            case "说道:「你去提水浇田。":
            case "说道:「我不是给过你任务了吗?提水浇田,快去!":
                App.Quest.WDJ.Type = "jiaoshui2"
                break
            case "说道:「你去把睡房的便桶全部倒进茅房。":
            case "说道:「我不是给过你任务了吗?把睡房的便桶全部倒进茅房,快去!":
                App.Quest.WDJ.Type = "maofang"
                break
            case "说道:「你去弄点烂菜叶喂猪。":
            case "说道:「我不是给过你任务了吗?弄点烂菜叶喂猪,快去!":
                App.Quest.WDJ.Type = "weizhu"
                break
            case "说道:「你去把书房书架上的书整理一下。":
            case "说道:「我不是给过你任务了吗?把书房书架上的书整理一下,快去!":
                App.Quest.WDJ.Type = "zhengli"
                break
            default:
                App.Fail()
                return
      }

很好,这样一个标准的提问功能就做好了。


正常情况下,大部分任务都不需要为提问做更多的触发了。

jarlyyn 发表于 2022-6-24 17:36:30

下一篇应该是迷宫篇

luoeric 发表于 2023-11-14 09:53:48

终于看懂30%,这个思路有启发啊,把所有的ask动作做成一个包。。。恩,我要学着搞搞
页: [1]
查看完整版本: 一步一步在北侠做机器人之 Ask篇-学会提问的艺术