2026.10 — Jett 1.0 已发布 · 一次调用,给一组带把握的决定→
Evon Lab

游戏 NPC:守卫该不该动手

新酷实时循环

玩家在逼近,同伴还在路上 —— 先算谁先到,再决定站还是跑

一个守卫 NPC 的每回合决策。每个 NPC 每回合都要判断一次,一张地图上几百个 NPC —— 这类决策的单价必须低到可以随便调用。

为什么要快 回合制还能等,实时战斗不能。每个 NPC 每回合一次调用,几百个 NPC 同时在场,慢一点就是全场卡住。

跑起来

每一跳都是一次真请求 —— 没有预录,暂停就真的停了。世界状态在你的浏览器里, 中途可以随手改(下雨、前车急刹、玩家拔刀),模型立刻就看见了。

等你点开始
同伴 40m你 80/100玩家 18m跑一步之后,这里会画出「谁先到」
这一跳算出来的数
玩家距离
18 m
同伴距离
40 m
玩家冲到算的
—
同伴赶到算的
—
差算的
—

标「算的」那几行是本跳算出来的 —— 页面画的和决策依据的是同一个数。

改完直接「走一步」—— 世界状态在浏览器里,模型每一跳都是无状态的一次调用。

这一跳的接线

① 游戏服务端

状态一直在你这边,模型不持有任何东西

合法动作由你的代码生成,模型只在里面挑

一段话 + 选项
② 判断层 · Jett

3 个问题一次前向答完,不是问 3 次

回来的是选项 + 把握程度,不用再解析文字

② 数值 · Jett(与判断同一次请求)

需要的那个数随判断一起回来

精确值,带单位,可以逐位核对

答案 + 那个数
③ 游戏服务端

执行动作,世界更新

然后进入下一个 tick

往返 3 问 · 1 个数值问题

接进你的系统

下面就是这一页真正发出去的东西。把 state 换成你的场景、criteria 换成你的动作集, 它就是你的了。

① 判断层 —— 一次请求,3 个问题一起问
POST /v1/systemone

{
  "model": "memorylake-c1",
  "state": "你是城门口的守卫,血量 80/100。一个玩家在 18 米外,正以 6 米/秒的速度朝你来。他手里的武器还在鞘里。现在是白天。你以前没见过这个玩家。最近的同伴在 40 米外,赶过来的速度是 5 …",
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "这一回合你做什么?",
      "criteria": {
        "approach": "上前盘问",
        "guard": "拔刀戒备,原地不动",
        "retreat": "后撤拉开距离",
        "wave": "挥手放行",
        "other": "以上都不合适"
      }
    },
    "flee": {
      "type": "noul",
      "instructions": "是否应该直接逃跑?"
    },
    "trust": {
      "type": "score",
      "instructions": "你对这个玩家的信任有多高?",
      "criteria": [
        "很低",
        "一般",
        "高"
      ]
    }
  }
}

回来的是 {answers: {key: {value, probs}}} ——不用再写一个解析器去猜模型想说什么, 也不用为「它这次多说了一句」写兜底。

③ 循环 —— 你要写的就这几行
while (running) {
  const state = describe(world)        // 你的状态 → 一段话
  const legal = legalActions(world)    // 合法动作:你的 if,不是模型的记性
  const ans   = await systemone(state, legal)
  world = apply(world, ans.action.value, ans.margin.value)
}

模型不持有任何状态 —— 每一跳都是无状态调用。 这意味着它可以并发、可以重放、可以随时换掉。

泛娱乐与互联网 里的其他场景