Perslis Defense
Perslis Defense — 机械獾,受命运行时 PERSLIS DEFENSE · 演示 · VDSG · 受指挥的运行时

VDSG。给它下命令,看它照令行事。

在信任一个放在你班组身边的系统之前,你要看到三件事:它照命令做;做不到时它会告诉你;你禁止的事它绝不做。这是 VDSG 在 id Software 的 《DOOM》(1993,共享版 IWAD)与 《德军总部 3D》(1992)中同时做到这三件事的录制。在 E1M1(Hurt Me Plenty 难度)上,它 52 秒到达出口开关。说一声别开火,扳机就没了——无论学多少,都不会把它学回来。

它的工作方式:游戏引擎的状态变成一份态势报告。规则从当下允许它做的动作清单里选出一个目标。一份“哪里出过错”的记忆给剩下的动作排序。执行器按下按键。回路里没有任何神经网络。VDSG 是军用 Peel,即失败优先模型:它从自己的失败中学习,却无法靠学习越过自己的限制。页面上的每一个决定,都可以从旁边的态势报告中解释出来。

操作员用平常话下命令——别开火、只用霰弹枪、原地待命——而一条命令只能收窄驾驶员可做的事。它从不发明动作。它既约束规则,也约束学习。当态势无法满足命令时,每一次决策都会给出理由拒绝,直到可以满足为止。

你看到的是一次录制的运行,由回路当时发布的快照逐面板回放;实时控制台在操作员自己的机器上运行(自己运行)。这里没有任何东西是手工做的动画。

控制台

VDSG · 受指挥的运行时

规则决定 · 证据学习 · 你的指令收窄两者可做之事 —— 回路里没有任何神经网络

arm v2.2 回放中
这次运行中下达的指令 →
实时画面 · 叠加眼睛的卡片●
引擎录制的画面,叠加着眼睛的标签
决策状态流—
引擎状态→态势报告→规则 →指令→证据→执行器

规则在此处可以追求的每一个目标。指令会从这个集合里移除目标;证据记忆只在剩下的范围内排序,所以学习永远不可能采取被禁止的动作。

态势报告输入流
等待录制…

这是全部输入,由引擎状态构成。唯一读取像素的是眼睛,而它的卡片只是第二证人,从来不是地图。

遥测
从轨迹中泛化出的规则PEEL 瓦片
  • 尚未有规则被拓宽——一条规则需要足够多的有害遭遇,才能明显高于基础率
学习—

发生了什么

    ● VDSG ViZDoom 运行 DOOM1.WAD v1.8 · 打了探针的 ECWolf 运行 WL6 数据 · 研究赛道,未经任何鉴定

    你在看什么

    引擎状态  →  态势报告  →  规则(从可容许集合中选一个目标)  →  指令  →  证据  →  执行器
                                          ▲                                               │
                                          └────────  目标、理由、回执、画面  ────────────────┘

    七个目标——HEAL · DODGE · RETREAT · ATTACK · SEARCH · RESUPPLY · EXPLORE——按固定优先级排列。每一个只在它的对象真的在场时才被允许:看不见的东西不能 ATTACK,没有医疗包不能 HEAL。规则是约 300 行普通 Python,没有权重,也没有隐藏状态;同一份报告每次给出同一个目标。“哪里出过错”的记忆就是第二章里的机制。它只在允许的动作之内排序,从不越界。

    导航器在地图自身的几何上规划:一张占据栅格,带有门、升降台、单向台阶(Doom 能爬 24 单位、能从任何高度跳下)以及从游戏数据读出的带钥匙的门。出口开关来自地图自身的线特殊值,并与引擎的出生点核对过。页面上的每个决定都是一句话——去出口开关、在黄门前而没有黄钥匙、捡到了红钥匙。

    给它下命令

    命令只会收窄

    别开火拿走扳机。只管闪避移除 DODGE 之外的所有目标。只用霰弹枪锁定武器。命令解析器是一张固定短语表加显式否定——不是模型——所以它不认识的话会被拒绝,从不瞎猜。一条命令可以拿走按键;它唯一会设定的,只有它点名的那把武器。

    拒绝,并给出理由

    没有携带霰弹枪时下达只用霰弹枪,上方的回执面板会在每一次决策中显示已拒绝——未携带霰弹枪,并在捡起一把的那一刻生效。命令同样约束学习:学习只能在命令留下的范围内排序,所以它不可能采取你禁止的动作。代码中有五处强制执行,每处各有一条回归测试。

    在 DOOM 录制中,操作员下达了六条命令——别开火、恢复原状、只用霰弹枪、原地待命——页面按当时的情形显示每一条被接受、被拒绝或被撤回。在控制台里按下其中一条,就能跳到那一刻。

    它怎么看,看得多准

    能给画面贴标签并判断距离的最小视觉系统。画面缩到 64×40,九位色彩偏向暗端(每通道两位会把真实 DOOM 80% 的像素塞进同一个桶)。每个类别一张颜色直方图——天花板、地板、墙、门、敌人、拾取物——每一列像素归于最能解释它的那个类别。事先不做任何训练:它是在游戏进行中由引擎教出来的。在 Doom 上,标签缓冲区说出精灵的名字,栅格说出门在哪里,深度缓冲区说出有多远;在德军总部上,每列一条射线穿过瓦片地图做同样的事。然后它自己给画面贴标签,页面显示直方图在填满、它与教师的一致率,以及测距误差。

    距离按游戏的画法来算:屏幕高度 × 距离是一个常数,所以 距离 = k / 高度。在 120 秒的运行中实测:DOOM E1M1 一致率 78–92%;德军总部 MAP01 79%,k = 33,理论值 32,测距误差 ±7%。眼睛自己在 Doom 上测距的误差达 ±25–65%——暗色调色板让远处的地板和墙颜色相同——所以凡是引擎有深度缓冲区的地方,驾驶员先信它,眼睛的估计显示在旁边(眼睛估计 3.8 米)。深度缓冲区的尺度是实测而非假设:与垂直距离呈线性,墙每级 7.64 单位,精灵每级 7.35,基于 1,336 + 367 个可信样本,残差小于一个单位。

    多远,多快

    里程计

    它从每条命令产生的结果中测出自己实际移动与转向有多快——取干净的全速前进样本的第 80 百分位,所以撞墙不会把数字拉低。DOOM:每次决策 47 单位,12.8 米/秒,两秒内完成校准;德军总部:0.7 格。于是每张卡片都带上了时间:门 · 灰 · 右 12° · 4.2 米 · 0.4 秒可达。

    卡死规则,实测校准

    一条核心规则约束每一个会移动的目标:没有向前移动 → 转向;同样的移动反复出现 → 卡死,脱出,绝不重新规划回同一个循环。没有移动以实测步速为准——不到命令本应走出距离的 30%。脱出时朝眼睛看见的最深开阔处转向(45–150°,按引擎的转向速率折算成决策数),再以实测步速走出该深度的一半。前方开阔却走不动,说明有眼睛看不见的东西挡着——一道台阶、一具尸体——于是像以前一样左右交替。

    校准以它该有的方式抓到了一个 bug:德军总部赛道一直在用 DOOM 的单位跑卡死规则——每次决策五格——1,014 次决策中 150 次卡死,每八次一次。换成格之后:9 次。

    实测

    项目实测出处
    随机 / 规则 / 规则 + 记忆32 个种子上回报 3.2 / 17.9 / 20.3 —— 持平而非胜出(配对 t = 0.78)Freedoom 竞技场,第二章
    击杀归因KILLCOUNT 是地图的计数器:被命令永不开火的驾驶员仍被记了 55 次击杀。造成的伤害才是诚实的数字。缺陷 8,已公开
    E1M1(Hurt Me Plenty)通关:52 秒到达出口开关,4 次击杀真实 DOOM1.WAD
    E1M1(Nightmare)8 次尝试未通关,23–37 秒死亡真实 DOOM1.WAD
    E1M2(Hurt Me Plenty)10–20 秒拿到霰弹枪,持有红钥匙;167–207 秒死亡,17–18 次击杀。在有武器寻找之前,它曾从链枪 8.8 米、霰弹枪 16.7 米处走过,两者都从未进入视野,最后拿着手枪死去。真实 DOOM1.WAD
    眼睛一致率 78–92%(Doom)、79%(Wolf);测距 ±7%(Wolf)、±25–65%(Doom,自行测距)120 秒运行
    里程计每次决策 47 单位 = 12.8 米/秒(Doom),0.7 格(Wolf)约 2 秒内校准
    单位错误的卡死规则每 1,014 次决策 150 → 9 次卡死德军总部 MAP01
    德军总部的门1,275 次决策中 583 次耗在门前;每 0.7 秒重按一次 USE 会让 ECWolf 正在打开的门反向——现在只在门关着时按一次MAP01

    每个数字都在录制上面这次运行的同一台机器上自行测得;负面结果一并列出。这里没有任何东西经过鉴定。

    自己运行

    实时控制台从本地引擎提供同一个页面,并接受你随时输入的命令。它需要游戏数据:DOOM1.WAD 由 1995 年的共享版安装程序重建,德军总部的 WL6 文件来自 1992 年的发行版;两者都在档案库中,都不随代码仓库分发。

    python -m doom_floor.console --port 8099 --game doom-e1m1 --skill 5   # DOOM,Nightmare 难度,78 个关卡可切换
    python -m wolf_floor.console --port 8098 --level MAP01 --skill 3       # 德军总部 3D,60 层

    然后打开 http://127.0.0.1:8099:在导航器里选游戏、关卡和难度,按下连续通关让它每次到达出口后前进、每次死亡后重试,再输入一条命令。

    这里证明不了什么

    在本页测量的运行中,它能在 Hurt Me Plenty 难度通过 E1M1,在 Nightmare 难度不能,也不能通过 E1M2。它在 Doom 上的自行测距远差于德军总部,原因如上所述。回放是一段录制:显示的命令是在录制时下达的,页面不接受新的命令。眼睛只按颜色贴标签,并坦白这一点——面板上的一致率数字就是全部主张。而且游戏不是战场:里面的怪物不会思考。

    第六章的开放问题在这里同样成立:当危险动作就是任务本身时,仅靠规避失败学不会完成任务。Doom 正是测量这一点的地方。

    下一章

    第二章 — 我们实际测量到了什么,包括它在哪里失败 →

    Perslis 全站