jarlyyn 发表于 2022-1-10 23:31:03

一步一步在北侠做机器人 行走限制版

年底较忙,外加更新客户端API,机器人没有什么更新

上线倒是发现有个行走限制的Patch,看了下,机器人也受影响,决定修正下。

其实修正的内容很简单,就是行走的时候计算下走了多少步,超过限制就进入和怕汉中失败一样的重试状态就行,说干就干,快马加鞭


jarlyyn 发表于 2022-1-10 23:34:37

本帖最后由 jarlyyn 于 2022-1-11 01:11 PM 编辑

首先,我们明显需要统计最近的行走部数,因此,我们需要先添加一个计时器

[]
ID = "gc"
Name = "gc"
Enabled = true
Hour = 0
Minute = 0
Second = 0.2
Send = ""
Script = "App.OnTimerGC"
AtTime = false
SendTo = 0
ActionWhenDisconnectd = true
Temporary = false
OneShot = false
Group = ""
Variable = ""
OmitFromLog = false
OmitFromOutput = false
用于清理过期的统计数据

入口代码里也要加一个相应的相应代码

App.OnTimerGC=function(name){
    App.Raise("gc")
}
触发一个gc事件

jarlyyn 发表于 2022-1-10 23:39:05

本帖最后由 jarlyyn 于 2022-1-11 01:11 PM 编辑

然后,我们在move.js里,需要统计一下最新的移动步数

    app.GetMoved=function(){
      gc()
      return moved.length
    }
    var moved=[]
    var gc=function(){
      newmoved=[]
      var now=(new Date()).getTime()
      moved.forEach(function(ts){
            if ((now-ts)<500){
                newmoved.push(ts)
            }
      })
      moved=newmoved
    }
    app.RegisterCallback("core.move.gc", function () {
      gc()
    })   
    app.Bind("gc","core.move.gc")
    app.RegisterCallback("core.move.onroomobjend", function () {
      moved.push((new Date()).getTime())
      app.OnStateEvent("move.onRoomObjEnd")
    })


很明显,我们创建了一个内部变量moved,用于储存近期行走的房间

在onRoomObjEnd里,负责向moved里推时间戳

把内部函数gc注册到gc事件里

然后增加一个App.Moved函数,用于调用gc,获取移动成功步数,

注意,gc事件在目前的代码里并不必要,只是为了以后可能会主动发送命令做准备

然后,在retry(行走失败)和 ignore(忽略的房间描述)的触发了,弹出最后一个时间戳

    app.Core.OnMoveRetry=function(name, output, wildcards){
      moved.splice(-1)
      app.OnStateEvent("move.retry")
    }
    app.Core.OnMoveIgnore=function(name, output, wildcards){
      moved.splice(-1)
      app.OnStateEvent("move.ignore")
    }

移动指令就修改完了。



jarlyyn 发表于 2022-1-10 23:42:12

最后,我们修改发送的频率。

很明显,我们修改的是移动发送的模式,按照我们的基础篇里,这明显就是载具负责的事情。

我们添加一个慢悠悠的载具slow

(function (app) {
    let Vehicle = Include("core/vehicle/vehicle.js")
    let Slow = function () {
      Vehicle.call(this)
      this.ID="slow"
      this.MultiStep=false
      this.Fly=true
      this.Sender=function(cmd){
            if (app.GetMoved()<5){
                app.Send(cmd)
            }else{
                app.OnStateEvent("move.retry")
            }
      }
    }
    Slow.prototype = Object.create(Vehicle.prototype)
    return Slow
})(App)
和run一样区别是禁止多步,发送时判断一下已经发送的是否大等于5

需要休息的话就触发个move状态的retry时间

否者直接发送

然后在载具的vehicle.js里进行调整

引入slow载具,设置为默认载具,

    let slow = Include("core/vehicle/slow.js")

    app.Vehicle=null
    app.Vehicles={
      Run:new run(),
      Go:new go(),
      Cart:new cart(),
      Slow:new slow(),
    }
    app.DefaultVehicle=app.Vehicles.Slow
    app.Vehicle=app.DefaultVehicle
    app.Drive=function(id){
      if(id){
            for (let key in app.Vehicles) {
                                if (app.Vehicles.ID == id){
                  app.Vehicle=app.Vehicles
                  return
                }
                        }
            throw "未知的载具 " +id
      }else{
            app.Vehicle=app.DefaultVehicle
      }
    }

好了。修改完毕。



jarlyyn 发表于 2022-1-10 23:44:33

最后,测试下机器人

walk.partor,locate都没问题,不需要改代码

明显会走4步停0.5秒

修改完毕

具体的patch 见

https://github.com/hellclient-scripts/pkuxkx.noob/commit/4facae4a6e560fe2aa8d303381c841f5840ac136

很明显,良好的架构对于一个机器的扩展和维护有很重要的价值。

bigb 发表于 2022-1-11 12:15:39

厉害。希望我能有看懂的一天。

nrm 发表于 2022-1-11 12:54:47

虽然程序我不懂,但是喜欢楼主这种分享编程思路的方式
赞一个

caisz 发表于 2022-1-11 13:04:23

厉害,学习了

jarlyyn 发表于 2022-6-16 12:47:08

之前不玩北侠,光这样改还是有点问题的。

首先,移动记录要有个全局的,同时也要有个buff缓冲,就是与其在mud里缓存,不如自己缓存

代码大体如下

    var moved=[]
    var movebuff=[]
    var gc=function(){
      newmoved=[]
      var now=(new Date()).getTime()
      moved.forEach(function(ts){
            if ((now-ts)<600){
                newmoved.push(ts)
            }
      })
      moved=newmoved
    }
   
    App.RegisterCallback("core.move.gc", function () {
      gc()
      if (moved.length<3&&movebuff.length){
            App.Send(movebuff.shift())
            moved.push((new Date()).getTime())
      }
    })
    App.SendToMoveBuff=function(cmd){
      gc()
      if (moved.length<3){
            App.Send(cmd)
            moved.push((new Date()).getTime())
      }else{
            movebuff.push(cmd)
      }
    }
    App.Bind("gc","core.move.gc")每0.6秒行走3次就堆入缓冲,这样在不太卡的情况下,任何一个一秒内不会连续发送超过6个移动命令(1.2秒周期,超过一秒)

其次,修改基础载具

(function(App){
    let _drivepath=Include("include/drivepath.js")
    let Vehicle=function(){
      this.TagDrive=false
      this.MultiStep=false
      this.ID=""
      this.RetryInterval=0.5
      this.Fly=false
      this.Sender=function(cmd){
            App.SendToMoveBuff(cmd)
      }
    }
    Vehicle.prototype.Send=function(cmd){
      this.Sender(cmd)
    }
    Vehicle.prototype.ConvertDrivePath=function(cmd,path){
      let p=_drivepath
      if (!p){
            throw "无效的drivepath"+path
      }
      p=p.replace("%1",cmd)
      return p
    }
    return Vehicle
})(App)
让所有的行走都走这个SendToMoveBuff,收工。

为了以防万一,也就是卡顿的情况下,在移动时出发的[命令加入缓冲],直接发送一个"move.retry"状态事件 到当前状态

当作爬山时需要等一等重走的busy一样处理。

这样尽可能的能解决移动时进入缓冲的问题


jarlyyn 发表于 2022-6-16 12:47:46

另外之后应该还会更新三篇

大体是

武当新人人物篇

迷宫篇

战斗篇。
页: [1]
查看完整版本: 一步一步在北侠做机器人 行走限制版