北大侠客行MUD论坛

 找回密码
 注册
搜索
热搜: 新手 wiki 升级
楼主: jarlyyn

一步一步在北侠做机器人

[复制链接]
 楼主| 发表于 2021-9-10 17:40:30 | 显示全部楼层
本帖最后由 jarlyyn 于 2021-9-10 05:51 PM 编辑

自己做客户端有一点好,就是可以根据自己的需求改接口。

比如做行走模块,我发现我最好能在房间里所有对象结束后直接触触判断。

实际在mud里,房间对象列完会有个> ,但位置是在提示行,只有在下一次输出(比如有人走过)的时候才会换行,然后触发触发器。

我直接加了个接口,让脚本判断下当前行,如果当前行内容是> 就强制换行,触发触发器。

这下直接就能在第一时间处理房间对象了。

效果见附件图

小齿轮是触发了触发器的行,鼠标移上去能看到触发了哪些触发器。

很明显,以最后一个小齿轮为例,不需要等护寺僧人走过来,那个 > 就触发了触发器了。

如果是mush的话,不知道新版本是否有api可以实现这个功能(记得plugin能实时处理包,当年做个一个处理 > 的东西)。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2021-9-10 17:46:56 | 显示全部楼层
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-11 00:59:46 | 显示全部楼层
本帖最后由 jarlyyn 于 2021-9-11 01:26 AM 编辑

好,恢复正常更新了。

下一步我们先做简单的行动,定位。

定位是一种模拟人行为的操作。

想想你刚玩mud,路还没认全时,迷路了怎么办?

至少我是做布朗随机移动,知道进入我认识的房间。

定位就是模拟这个的。

但是,纯粹的随机移动从逻辑上是会回到原点,在原点附近移动的。

所以,我们需要去重,尽量向较远的地方移动,不要走回头路。

因此,我们的逻辑是

  • 定义一个最大距离,不超过什么范围
  • 进入一个房间时记录所有出口,过滤下出口,不进奇奇怪怪的地方
  • 没到最大距离时,进入第一个没有走过的出口,并记住从哪个出口可以回去。如果没有对应的出口,就假设可以从最后一个出口回去
  • 到了最大距离时,回退一部,继续走下一个没有走过的路口
  • 所有的出口都走过时,再回退一部
  • 任何一个房间是我们认识的,就成功定位,结束行走
  • 如果无路可退,则说明我们行走失败。

好,确定好逻辑,我们就开始写代码了。

首先,由于这是个复杂模块,我们引入js的类,定义一系列的类。

之所以用类,不是为了面向对象(OOP)。进过这些年的代码,我对类的继承和多态不是特别感冒,只是为了封装,将数据和方法放在一起,但又互相分开。

写代码没有银弹,至少OOP不适合多变的mud脚本需求。

首先,我们定义什么是正常出口,就是可以回退的出口:

https://github.com/hellclient-sc ... include/backward.js

其次,我们定义一个数据结构,用于计算下一步该走什么出口。由于是主逻辑,我加了注释以便阅读

https://github.com/hellclient-sc ... t/include/locate.js

最后,我在外面定义了一个Move类,用于响应mud触发和事件,调用数据结构,进行移动

https://github.com/hellclient-sc ... script/core/move.js

好了,基本的代码就是这些,让我们看看效果吧



北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-11 01:12:34 | 显示全部楼层
由于我们只认识扬州的几个地点,就让我们在扬州进行测试

首先,让我们在扬州南门,进行5步的定位

在南门输入 /(new App.Move("locate",5)).Start()

机器飞速的逛街之后,到了认识的扬州当铺,骄傲的宣告自己定位成功了



好极了,我果然是扬州认路王。

然后,让我们挑战一下自己,去曲阜认路

让我们在鼓楼 /(new App.Move("locate",5)).Start() 一下

一阵逛街之后,回到鼓楼,提示找不到。当然啊,曲阜离开扬州超过5步啊



让我们自信一下,/(new App.Move("locate",20)).Start(),走20步看看

天哪,摔晕了



mud好危险,妈妈我要回家!!!

这说明一个问题。

定位,只有在你确认周围很安全,或者房间信息非常全,只是分辨不出重名房间才适合使用。

不然的话,意外太多,并不实用。





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-11 01:21:17 | 显示全部楼层
本帖最后由 jarlyyn 于 2021-9-11 01:52 AM 编辑

接下来,我们要解决下一个问题

让我们回到扬州武庙,/(new App.Move("locate",20)).Start() 开始定位

突然发现,机器不动了,说我不是神,下不去



这就设计到行走模块的一个复杂点了。行走失败。

之所以说定位做起来简单,就是定位处理行走失败很简单。

设置一个计时器,发送命令后记时,进入下一个房间后关闭。

如果超过1秒,说明行走失败,跳过这个出口去下一个。

反正本来就是定位,也不存在走错。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-11 01:49:28 | 显示全部楼层
好,让我改下代码。

在locate.js里加入 Skip方法

https://github.com/hellclient-sc ... t/include/locate.js


在move.js里加入响应超时的函数 OnMoveStepTimeout和具体处理的Move.OnStepTimeout

https://github.com/hellclient-sc ... script/core/move.js


在游戏里加入一个叫steptimeout,间隔1秒默认不开启的timer。

然后回到武士会客室,/(new App.Move("locate",5)).Start()

在武庙尝试d,一秒之后放弃继续定位,立刻在醉仙楼定位成功了



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-13 20:25:05 | 显示全部楼层
一个周末过去了。

我们接下去要做的是按路径巡查功能。

在做之前,我规划了下代码,大概会有4种甚至更多的行走方式。

都堆在move.js的话太臃肿了。就用利用工厂模式的设计模式,把他们抽象出来

先抽象出一个基础的move.js

https://github.com/hellclient-sc ... t/core/move/move.js

然后扩展出一个locate.js

https://github.com/hellclient-sc ... core/move/locate.js

这样core/move.js里就只有对外的接口,回调和触发了,非常干净

https://github.com/hellclient-sc ... script/core/move.js

启动locate的代码也变成了 /App.NewMove("locate",5).Start()


北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-13 20:32:09 | 显示全部楼层
好,接下来做巡查patrol 功能。

patrol功能也简单,就是建立一个路径,依次弹出 第一个命令前进,在确认进入新房间后,掉回调(on_step)判断

如果on_step返回true,就继续行走

如果on_step返回false,就暂停(Pause)整个移动,发送事先设置好的命令,等待处理完后Resume()继续走完或者直接Stop()

这是巡查的数据结构,非常简单

https://github.com/hellclient-sc ... t/include/patrol.js

这是巡查的处理逻辑

https://github.com/hellclient-sc ... core/move/patrol.js

也很简单

注意

https://github.com/hellclient-sc ... t/core/move/move.js

里的TryMove

这是行走的最复杂的地方

迷宫/有busy的路径/乘船之类都需要在这个方法里实现



https://github.com/hellclient-sc ... script/core/move.js

里注册了一个测试用回调core.move.onStepRoomObj

就是测试当前房间里是否有指定对象,有指定对象就下达对应命令,同时只处理一次。

这应该是很常见的场景
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-13 20:40:55 | 显示全部楼层
接下来我们就是要测试下。

首先,我们先定义个路径。

比如我们从 扬州广场->西门->东门->扬州广场->北门->南门->广场,也就是

  1. w;w;w;e;e;e;e;e;e;w;w;w;n;n;n;s;s;s;s;s;s;n;n;n
复制代码

找著名街溜子 托钵僧喝酒

在扬州广场执行命令

  1. /App.NewMove("patrol",new App.Path("w\;w\;w\;e\;e\;e\;e\;e\;e\;w\;w\;w\;n\;n\;n\;s\;s\;s\;s\;s\;s\;n\;n\;n".split("\;")),"",{"OnStep":"core.move.onStepRoomObj","StepData":{"Obj":"Tuobo seng","Cmd":"ask tuobo seng about 下班一起喝酒不"}}).Start()
复制代码
居然发现这秃驴摆刁


算了,不和他一般见识,我们把剩下的路径走光

  1. /App.Data.Move.Resume()
复制代码


果断走完路径,走到扬州广场,并提示巡查完毕。

很好,我们的巡查模块还是很顺利的。

这其实是侠客行类mud常用的任务类型之一。

主要正对的是房间,比如,在路径里每个房间执行一次search,寻找宝物。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2021-9-14 10:57:43 | 显示全部楼层
下一步是行走模块了

我们这次做一个多步行走的模块


行走模块的数据结构比较简单,待行走的路线 和 移动中(多部)的路径就可以了

https://github.com/hellclient-sc ... ipt/include/walk.js

然后是行走模块的业务部分

https://github.com/hellclient-sc ... t/core/move/walk.js

里面的逻辑很简单

如果下一个动作是通用的命令,而且队列没到达设定的最大长度的话,把命令压入队列

接着一次性发送所有命令

最后在进入房间后进行依次核销,全部核销完进入下一个步骤,直到结束。

注意,这里的核销是个超简化部分,实际会复杂很多


北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大侠客行MUD ( 京ICP备16065414号-1 )

GMT+8, 2024-3-29 07:17 PM , Processed in 0.010073 second(s), 13 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表