跳转至内容
  • 欢迎
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(不使用皮肤)
  • 不使用皮肤
折叠
品牌标识

Hellclient 社区

  1. 主页
  2. Script脚本
  3. 深入浅出制作全自动Mud机器人-移动失败处理

深入浅出制作全自动Mud机器人-移动失败处理

已定时 已固定 已锁定 已移动 Script脚本
mud机器人全自动代码范例
1 帖子 1 发布者 14 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • jarlyynJ 离线
    jarlyynJ 离线
    jarlyyn
    编写于 最后由 编辑
    #1

    对于整个移动模块来说,最核心的可能就是移动失败处理了。

    本身对于大部分系统来说,失败/意外流程处理都是最复杂的。而移动模块的失败处理大部分面对的是wiz的恶意,所以更强调可扩展性和可维护性。

    对于移动失败,本质来说,就是:

    1. 发出移动指令
      2.预期会收到成功信号,或者各种失败信号
      3.如果收到成功信号,则对当前移动的这一步进行核销。
      4.如果受到的是失败信号,则根据具体的失败信号数据进行处理,重规划路线/重试/放弃失败。

    因此,移动失败是一个很典型是预期管理

    我做的预期管理模块有很大一部分目的就是为了移动失败处理设计的。如果是其他语言/客户端的机器,也能通过各种类库或者触发器分组的功能进行预期管理。

    以newhelljs为例,代码地址

        App.Map.StepPlan = new App.Plan(
            App.Map.Position,
            function (task) {
                App.Move.RetryStep = false
                let tt = task.AddTimer(App.Map.StepTimeout, function (timer) {
                    return App.Map.OnStepTimeout()
                }).WithName("timeout")
                task.AddCatcher("core.longtimestep", function () {
                    tt.Reset(App.Move.LongtimeStepDelay)
                    return true
                })
    
                task.AddCatcher("core.retrymove", function () {
                    App.Move.RetryStep = true
                    return true
                })
                task.AddCatcher("core.movereset").WithName("movereset")
                task.AddCatcher("core.wrongway").WithName("wrongway")
                task.AddCatcher("core.walkbusy").WithName("walkbusy")
                task.AddCatcher("core.walkresend").WithName("walkresend")
                task.AddCatcher("core.walkretry").WithName("walkretry")
                task.AddCatcher("core.walkfail").WithName("walkfail")
                task.AddCatcher("core.blocked2", (catcher, event) => {
                    if (App.Core.Room.Current.ID == "") {
                        return true;
                    }
                }).WithName("blocked2")
                task.AddCatcher("core.blocked", (catcher, event) => {
                    catcher.WithData(event.Data)
                }).WithName("blocked")
                task.AddCatcher("core.needrest").WithName("needrest")
            },
            function (result) {
                switch (result.Type) {
                    case "cancel":
                        break
                    default:
                        switch (result.Name) {
                            case "timeout":
                                break
                            case "movereset":
                                App.Map.Room.ID = ""
                                App.Map.Retry()
                                break
                            case "wrongway":
                                if (App.Move.RetryStep) {
                                    App.Map.Resend(0)
                                    return
                                }
                                App.Map.Room.ID = ""
                                App.Sync(() => {
                                    App.Map.Retry()
                                })
                                break
                            case "walkbusy":
                                App.Map.Resend()
                                break
                            case "walkresend":
                                App.Map.Resend(0)
                                break
                            case "walkretry":
                                App.Map.Retry()
                                break
                            case "blocked":
                                App.Move.OnBlocker(result.Data)
                                break
                            case "blocked2":
                                App.Core.Blocker.BlockStepRetry()
                                break
                            case "needrest":
                                App.Move.NeedRest()
                                break
                            case "walkfail":
                                App.Move.OnWalkFail()
                                break
                            default:
                        }
                }
            }
        )
    
    

    很明显,是对于整个移动做了预期。

    首先这个预期是基于App.Map.Position的

    Map库中有两个Position

    • App.Map.Position 当前房间范围
    • App.Map.MovePosition 当前移动的范围

    所以,当成功移动时,整个移动处理会因为离开范围而被"cancel"

    当没有Cacnel时,说明意外出现了。

    不同的信号(事件)会根据在switch里做分支判断,调用各种异常。

    这也就是整个失败处理的底层逻辑

    在 完全基于hmm开发的hongchengjs中,我为了可维护性,做了些调整,将常见的移动失败作为一个文本保存,启动时调入内存放在一个Hash表里,直接做表匹配模拟事件,算是一个小的结构优化。

    代码地址

    在失败处理中,有四个处理是最为典型的

    第一个是路线错误

    也就是"core.wrongway"事件。

    触发后会清空当前房间信息,调用当前移动的Retry方法进行重新规划和移动。

    第二中是路线禁用

    也就是"core.blocked2"事件。

    出发该事件后,说明被拦截,而且不该击杀然路Npc,会把当前房间和目标房间的出口临时禁用,然后重新规划路线。

    第三种是插入战斗

    "core.blocked"事件

    会把当前移动进行快照,然后击杀拦路npc,再对快照进行还原,继续移动。也是很经典的形式。

    最后是重新规划

    "walkretry"事件

    这个事件和路线错误一样都是直接调用重新规划。

    区别是这个事件本质是一个衍生事件,在我的事件系统中,一般会调用Filter进行处理,一般是调整当前Move的上下文标签。然后再根据最新上下文标签进行重新规划。

    这四种基本就是主要的移动失败处理的内容。当然,不同的Mud可能还会有一些细节上的调整。

    移动失败处理的主要处理方式就是

    • 重试。
    • 调整上下文,重新规划,避免失败出口。
    • 挂起移动,解决意外,还原移动并继续,
    1 条回复 最后回复
    • jarlyynJ jarlyyn 被引用 于这个主题
    回复
    • 在新帖中回复
    登录后回复
    • 从旧到新
    • 从新到旧
    • 最多赞同


    • 登录

    • 没有帐号? 注册

    • 登录或注册以进行搜索。
    Powered by Herbrhythm.
    • 第一个帖子
      最后一个帖子
    0
    • 欢迎
    • 版块
    • 最新
    • 标签
    • 热门
    • 用户
    • 群组