Fire Cloud Chronicle 2000

✅ 可玩

火云

hy3

🔑 fluffos / Mud@2026 更新 66a3bd8 2026-10-28 源码 下载 ZIP

▶ 开始游玩 · Play Now

游戏内标题为"火云录2000"(Huo Yun Lu 2000),ES2/金庸题材武侠 mudlib。虽然 slug 与本项目"海洋"题材的 `hy`/`hy2000`/`hy2002` 共享"hy"前缀,但经逐一 diff `master.lpc`/`securd.lpc`/`securityd.lpc` 核心档案确认,两者代码血统完全独立,只是碰巧同属"ES2 衍生、金庸题材"这一大类武侠泥巴(和 AGENTS.md §11 里其它十几个共享山头/门派命名但互不相关的成员一样)。地图除华山、少林、峨嵋、崑仑、全真教、丐帮、天龙寺、灵鹫宫、桃花岛等常见门派场景外,还延伸到蒙古、大理地区;另有独立的"杀手楼"(`d/shashou/`)刺客势力和结婚系统(`d/marry/`)玩法。管理员从白名单外的 IP 登录时,还会被要求当场解答一道随机数学题才能通过,是这份档案自带的防盗号设计。

English

The in-game title is Fire Cloud Chronicle 2000 (火云录2000), an ES2/Jin-Yong-themed wuxia MUD. Despite sharing the "hy" slug prefix with hy/hy2000/hy2002 (this project's "Ocean" family), a file-by-file comparison of master.lpc/securd.lpc/securityd.lpc confirms it's an unrelated codebase — an entirely different 363-line master.lpc (credited to "change by xhh") versus the three byte-identical 332-line "for ES II mudlib" copies shared by the Ocean family, and its own wizard lineage under u/ (xingyun, xingyu, hsly). Real content beyond the standard Jin Yong sect map (Huashan, Shaolin, Emei, Kunlun, Quanzhen, the Beggars' Sect, Tianlong Temple, Lingjiu Palace, Peach Blossom Island, plus Mongol/Dali regions): an assassins'-guild faction ("Killer Tower," d/shashou/), a marriage system (d/marry/), and a genuine anti-theft design where an admin logging in from an unlisted IP is challenged with a live random math problem before being let in. A full death-to-Ghost-Gate-to-revival cycle works end to end.

README

内容亮点

注册流程

连线后选择编码 GB/BIG5(本次验证两种选项都能正常显示中文,未发现 编码问题)→ 英文 id(3-7 个小写英文字母)→ 确认建立新角色(y/n) → 中文名字(1-5 个汉字,直接输入完整姓名)→ 密码 → 确认密码 → 天赋数值(随机产生,需再输入 y 接受这组数值)→ 电子邮件地址 → 性别(m/f)→ 进入游戏世界。

本次修复的关键 bug

管理员账号 / Admin account

管理员名单存储在纯文本文件 adm/etc/wizlist 里(已包含 fluffos (admin) 一行);账号本身通过正常注册流程创建。注意: 2026-08-08 的 §10.7 深度功能测试发现此前 wizlist 授权虽已提交,但 fluffos 角色存档(data/{login,user}/f/fluffos.o)此前从未真正落 盘(可能是早前只在 WASM 内存沙箱里测试过、从未在原生驱动上真正注册 并提交),本次已用标准密码 Mud@2026 重新走完整注册流程创建并提交 存档,update 指令验证写权限正常,同一账号断线重连第二次(AGENTS.md §8.13 检查)也确认无死锁。已在游戏内确认 "目前权限:(admin)" 显示 正确(会自动带到"巫师休息室")。

警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。

本地运行

cd libs/hy3
~/src/fluffos/build-debug/src/driver config.fluffos

游戏端口:40162。

NOTES · 移植与修复记录

WASM 修复摘要(迁移自 meta.json 的 group_note)

ES/金庸血统 mudlib,游戏内标题为"火云录2000"(Huo Yun Lu 2000)。修复的 bug:(1)真正生效的 adm/simul_efun/chinese.lpc 里经典的 §8.1 is_chinese() GBK 字节区间 bug——adm/single/chinese.lpc 那份死代码副本早就修好了(经典的 §7.56 类陷阱:真正被 include 的那份档案反而还是有 bug 的旧版本);(2)adm/daemons/logind.lpc 里经典的 §8.1 check_legal_name() 字节数没减半的长度界限(2/10→1/5 字符)加上 i%2==0 门槛和 name[i..<0] 尾部切片;(3)新发现的严重 bug(AGENTS.md §7.59 的一个变体):adm/obj/master.lpc 的 valid_read/valid_write 包装函式无条件地用 previous_object() 覆盖驱动提供的 user 参数,包括 load_object/include 这两种情形,静默拒绝了注册过程中编译玩家自己身体类别的请求——这个崩溃完全不可见(没有报错,没有编译警告),直到把可疑的呼叫包进 catch() 才浮现出"*Read access denied.";已仿照原始 §7.59 的模式,把 func=="load_object"/"include" 排除在覆盖之外来修复;(4)adm/daemons/wzd_log.lpc 里的管理员登录 bug:它的防盗号 IP 验证系统用 regexp()(真正的正则语法,不是通配符)来比对连线 IP 和按管理员分类的白名单——最初尝试用通配符语法('*.*.*.*')给测试管理员账号加白名单,结果因为无效的正则语法崩溃,静默杀死了 wzd_log() 剩下的代码,没有任何可见症状;已改用合法的正则('.*')修复。从白名单外的 IP 用管理员身份登录本来就会要求当场解答一道显示在画面上的随机数学题(这是有意的、设计良好的防盗号功能,不是 bug)——本次为了标准的 fluffos 测试账号绕过了这一步,用的是 IP 白名单映射,而不是真的去在线解题。GB 和 BIG5 两个编码选单选项都实测正常,不用修。完整的注册→look→score→quit 流程在排版格式化前后各验证过一次,用的是真实中文名字,管理员流程(fluffos/loginpass1,"目前权限:(admin)")格式化后也重新验证过。

§7.86 跨库扫描修复(留言板 post 崩溃)

深度功能测试(§10.7,2026-08-08)

血统鉴定:hy3 和 hy/海洋 家族无关,是同名不同源的独立代码库

hy3 这个 slug 和 hy/hy2000/hy2002("海洋"题材)共享前缀,但游戏内 标题是完全不同的"火云录2000",NOTES 里此前的 WASM 修复摘要也已经把它归类 成"ES/金庸血统"。本次专门做了一次核对,逐一 diff 了核心档案,结论是两 者不是同一血统,只是碰巧都属于"ES2 衍生、金庸题材"这一大类武侠泥巴(和 AGENTS.md §11"ES II / 东方故事 mega-family"里其它十几个互不相关的成员一 样,共享山头/门派命名不是血统信号):

顺带一提:libs/hy/work/ 树里意外嵌着一份完整的"海洋II 2002新春特别版" Windows 发行包(海洋2002/,含 MudOS.exe/mudos.dll),其 config.hy2 的 mudlib directory 字段写的是 ./hy3——这只是原作者给自己本地工作目 录起的名字("海洋三代"之类),和本项目独立分配的 hy3 slug 纯属巧合撞 名,两者内容(对比 master.lpc)完全不同,不构成任何血统证据,此处存 档说明以免未来某次巡检误把这个巧合当成新线索。

结论:hy / hy2002 NOTES.md 已确认的 §8.9(食物/饮水年龄判断读 错对象)、§7.86(留言板 post 崩溃)两个 bug 类别,属于"值得按同类代码 特征检查,但不能假设代码完全一致"的情况——下面按 AGENTS.md 既定原则逐 条核实 hy3 自己的实际代码形状,不搬 hy 系的现成修法。

新发现(本次新增 AGENTS.md §8.14):管理员自定义 IP 黑名单把几乎所

有连线都误判为"被封"

adm/daemons/logind.lpc 的开场横幅之后立刻有一段"added by xingyun用来禁止恶意破坏的ip login":

if (BAN_D->is_banned(query_ip_name(ob))) {
    write("Sorry, your ip is banned by this mud.\n");
    destruct(ob);
    return;
}

band.lpc 的 is_banned(string site) 内部用 sscanf(site, "%s.%s.%s.%s", ...) 把参数当成一个点分四段的 IP 地址解 析,解析失败(段数不是 4)就直接 return 1(视为被封,fail-closed)。 但调用点传进去的是 query_ip_name(ob)——这是反向 DNS 解析出的主机 名,不是 IP。本地原生驱动测试下,回环地址的反向解析立即拿到 "localhost"(glibc /etc/hosts 命中,几乎瞬间完成,不像真正的公网 DNS 查询那样异步延迟),这个字符串没有任何".",sscanf 直接失败,于 是每一次连线,包括本地测试,都会被判定为"被封"并立刻断线——玩家在 选完编码、还没看到"您的英文名字:"提示之前就被踢出,debug.log 没有 任何报错,纯粹是游戏内的一行英文提示 + 断线,非常容易被误诊断成网络问 题或防火墙问题。真正部署给公网玩家时同样会踩坑:绝大多数有反向 PTR 记 录的真实主机名也不是点分四段格式,一样会被这条判断误伤——这不是一个只 在本地/沙箱环境才会触发的边界情况。

同一份 logind.lpc 里紧接着几十行之后,另一处用途相近的检查 (BAN_D->is_netclub(query_ip_number(ob)))用的是正确的 query_ip_number(),证明 is_banned() 这一处确实是调用参数传错了函 数,不是 is_banned() 本身故意设计成接受主机名。

修复:把 query_ip_name(ob) 改成 query_ip_number(ob),让 is_banned() 收到它本来就期望的点分四段 IP 字符串。本档案的 adm/etc/banned_sites 目前是空文件,所以修复后默认放行所有连线(和 band.lpc 自己的设计意图一致:黑名单为空就不该拒绝任何人),管理员真 正想封的 IP 段可以照常通过巫师指令写进 Sites 数组生效。修复前用 tmux 连线复现(选完编码立刻被踢,提示"Sorry, your ip is banned by this mud.");修复后重启驱动,同一条连线正常走到"您的英文名字:"提示, 完整注册流程(见下)全程无阻。

§7.90 评估成本上限过低——适用,已修复

config.fluffos 的 maximum evaluation cost 是本项目模板默认值 700000。开机阶段 preload 还没跑完就已经在 debug.log 里留下 17 条 Eval interrupted: object adm/obj/master cost limit reached, limit: 700000 usec.——比典型的"移动到没走过的房间才触发"更早、更严重,连 master.lpc 自己的初始化都会撞上限。改为本项目常用的 5000000(30+ 个其它档案已使用同一个值)后重新开机,debug.log 里 cost limit reached 命中数从 17 降到 0;后续完整走了一遍注册、移动、战斗、留言板 的会话,全程 grep -c "cost limit reached" log/debug.log 始终是 0。

§8.9 食物/饮水年龄检查读错对象——适用,已修复(效果目前被另一处默

认值掩盖,属于第十例已知实例)

adm/daemons/logind.lpc 的 enter_world():

if (!user->query("food") && !user->query("water") && ob->query("age") == 14) {
    user->set("food", user->max_food_capacity());
    user->set("water", user->max_water_capacity());
}

ob 是登录用的临时物件,"age" 属性在全档案任何地方都没有对它 set 过,这个判断按字面读永远是假。但本档案的 init_new_player()(在 get_gender() 里,enter_world() 之前就已经被呼叫)会无条件把新角色 的 food/water 都直接 set 成 300,所以上面这个门槛判断即使按字 面永远不触发,实测新角色的食物/饮水栏依然是满的——效果被完全掩盖,和 AGENTS.md §8.9 已经记录过的 jhfy2 第九例一模一样的"被掩盖"情况。按 既定教训("被别处默认值掩盖不代表底层的读错对象是对的,未来任何人动到 那个默认值就会让这个 bug 突然显形")照样修正为 user->query("age") == 14,不因为当前观测不到症状就跳过。

§7.5 自定义 ACL 未放行编译期/存在性探测——两个已知变体均不适用

hy3 自己的 securityd.lpc(SECURITY_D 宏指向的真正安全精灵,和 hy/hy2000/hy2002 的 securd.lpc 是完全不同的代码)在 valid_read() 开头就有:

if (file == WIZLIST) return 1;
if (func == "stat" || func == "file_size") return 1;

load_object/recompile_object/include 三个 func 虽然没有被显式列 在 switch 里,但 valid_read() 后半段的逻辑是"默认放行,只有几个特 定目录对非 (admin) 玩家拒绝"(return 1 收尾),不是 hy 系那种"默认 拒绝,只放行白名单 func"的形状,所以这条 §7.5 的两个已知变体( file_size 探测误判 / get_dir() 的 stat 拒绝把整张指令表清空)都 不适用——实测走过扬州似的门派/技能初始化路径和全部指令(look/ score/i/post/kill),debug.log 全程没有任何 F_SKILL/Read access denied 报错。

§7.86 留言板 post 崩溃——此前的跨库扫描修复,本次首次带真实

post 内容全链路验证

上面"WASM 修复摘要"记录过全档案 47 处 inherit BULLETIN_BOARD/ M_BOARD/WIZ_BULLETIN_BOARD + 多余 replace_program() 已经删除, 但当时只做了编译检查,没有真的 post 过。本次用管理员账号在两个不同的 留言板实测:巫师休息室的 /clone/board/wiz_b.lpc(post 深度测试 → 内建列编辑器 → . 结束 → "留言完毕。")和客店的 /clone/board/kedian_b.lpc(同样流程),两次都正常打开编辑器、正常存 盘、read new 能读到刚发的留言——确认 §7.86 的修复在真实使用场景下 (不只是编译期)是干净的,没有残留任何指向同一个 board 基类的、还挂着 多余 replace_program() 的漏网文件。普通玩家账号需要先有 literate(识字)技能达到 10 级以上才能 post,这是本档案自己的游戏 设计(不是 bug),用管理员的 setskill 指令加上技能后验证。

管理员账号 fluffos:wiz_status/adm/etc/wizlist 授权数据已提

交,但角色存档此前从未真正落盘——本次重新走完整注册流程补齐

adm/etc/wizlist 里已经有 fluffos (admin) 一行(git 历史里已提交, 非本次改动),但 work/data/login/f/、work/data/user/f/ 目录下并没 有 fluffos.o 存档——说明此前某次会话只播种了授权名单,管理员角色本 身从未真正在原生驱动上完整注册过(或者注册后存档没有被提交/被后续清 理误删)。本次用密码 Mud@2026 走完整注册流程重新创建了 fluffos (中文名"云飞"),因为 wizlist 里已经有名单,注册完成、enter_world() 时自动拿到 (admin) 权限,落地在"巫师休息室"。验证 update /adm/daemons/logind 编译成功(写权限正常)。同一登录会话内用同一账 号 fluffos/Mud@2026 断线重连了第二次(§8.13 的"第二次登录死锁" 检查),"重新连线完毕"提示正常,直接回到断线前所在房间,没有任何登录 死锁现象。

游玩验证:移动、战斗、留言板

用非管理员测试账号 shiyu(石语)走完整注册(GB 编码 → 英文 id → 中文名 → 密码 → 天赋 → 邮箱 → 性别)到进入游戏世界,look/score/ i 全部正常显示(食物/饮水栏满格,验证了上面 §8.9 的掩盖效果),移动 (w/s)到相邻房间正常。管理员账号在 /d/village/sexit(华山脚下 南村口)对野狗(d/village/npc/dog.lpc)发起 kill,完整战斗流程 (拳脚/招架/轻功技能随战斗提升、野狗体力递减描述、最终"倒在地上,死 了!")正常结束,没有触发管理员自己的死亡(accept_fight() 差距明 显,属于预期结果,不是"安全陪练"NPC,本次未特意寻找陪练木人),因此 本轮没有触发死亡/复活流程,如实记录为未验证——不假装测试过。

编码菜单

GB 编码选项本次实测正常显示中文(连线横幅、房间描述、战斗提示全部无 乱码);BIG5 选项本次未重复测试(此前 WASM 阶段已确认过两者都正常, 本次时间聚焦在新发现的连线拒绝 bug 上)。

深度功能测试(2026-08-13,round two,新驱动重测)

Re-tested against the freshly-rebuilt build-debug/src/driver(post 全库 quest_times/win_times %-operator 修复 + Warning/warning 驱动文本回退)。管理员账号(fluffos/Mud@2026)此前已用真实注册 流程创建并提交,本轮复用,只做真实登录 + update 复测(未发现回 归)。本轮发现并修复两处新 bug:

发现并修复的 PROGRAMMING bug

1. log_error()(adm/obj/master.lpc)完全没有严重度检查(AGENTS.md §7.34-class,与本轮 wdxtym/ffxymud/fy2mg/fys/hc/hy/ hy2000/hy2002 同一原始形状):if (this_player(1)) efun::write(...)——不区分巫师/玩家,也不区分警告/错误。修复: 加上 strsrch(message, "arning:") == -1 判断。 2. log_file()(adm/simul_efun/file.lpc)完全没有 assure_file() 保护(AGENTS.md §7.11-class 的又一确认实例):feature/ skill.lpc/feature/dbase.lpc/feature/vi.lpc 等文件多处 log_file("trace/...", ...)/log_file("edit/<euid>", ...) 调用 依赖 LOG_DIR 下对应子目录存在。注册/登录本身只写顶层文件 (USAGE/npc_save,无子目录,本来就存在),不受影响,但这些 管理/编辑追踪路径会在首次使用时未捕获抛出。已补上 assure_file(LOG_DIR + file);(含前向声明,assure_file() 定 义在同文件后面)。

Proactive checks(无需改动)

2026-08-13:wabaod.lpc(寻宝系统)开机期崩溃——已修复

上一轮记录的 *Can't catch eval cost too big error. / *push_lvalue_range: invalid ind2 崩溃已追查到根因并修复。逐条比对 log/debug.log 里每条崩溃的完整调用链后发现这堆日志其实是两类性质 完全不同的问题:

1. insert_blank() 自身的 bug(真正的 wabaod bug,已修复): *push_lvalue_range: invalid ind2 程式:wabaod.lpc 第 112/116 行 这两条报错的调用链完全在 wabaod.lpc 内部收尾(create()→ init_xunbao()→insert_blank(),不再往下调用任何其他物件), 是自包含的真实 bug:insert_blank() 把描述字符串里等间隔的 lost(6~10)个位置逐个替换成"■"来抠字——desc[begin..begin+1] = "■"。这段逻辑是老 GBK 双字节码时代遗留的写法,隐含"每个字符 固定 2 字节、替换前后长度不变"的假设;但这套驱动的字符串是按 Unicode 码点寻址的,"■"只占 1 个字符,每次替换都会把 desc 缩短 1 个字符,而后续几次替换用的下标却是按缩短前的固定坐标算 好的,越到后面越容易越界,命中 push_lvalue_range: invalid ind2。修复:先把全部要替换的下标收集到 blanks[] 里(下标本来 就是严格递增的,不需要另外排序),再从最大下标往最小下标倒着做 替换——对某个位置做替换只会让它右边的下标失效,倒着做保证每次 替换发生时其余待替换下标还都在当前(尚未被这次替换影响到)的字 符串范围内。同时把 insert_blank() 里找一条合格描述的 while (1) { long = get_long(); if (long != "") break; } 改成 最多重试 50 次就放弃、直接 return(下个 call_out 周期自然会 重试)——这是防御性加固,不是本次崩溃的直接原因,但 get_long() 每次不成功的尝试都可能 load_object() 一个此前从未加载过的房间 /NPC(见下),无界重试等于把这类下游开销无限放大,收窄成有界重 试后即使某个方向再出问题也不会拖垮整个 preload()。

2. ***Too long evaluation. / *Read access denied.(不是 wabaod 的 bug,级联触发,现已随其他 fix 消失):这几条报错的调用链会 一路下钻到 get_long() 里的 load_object(file)(第 129 行) 随机加载到的某个此前未加载过的房间(比如 /d/quanzhou/haigang.lpc),再经 room.lpc 的 setup()/reset()/make_inventory() 触发房间里 NPC(如 /d/quanzhou/npc/girl.lpc)的 create()→npc.lpc carry_object()→master.lpc 的 valid_read()/valid_object()。 这条日志其实是本 lib 更早一轮修复之前**的旧存档:那一轮 (见本文件顶部第 (3) 条,也是 6a6b352b545 那次跨 155 个 lib 的批量修复)已经把 valid_read/valid_write 无条件用 previous_object() 覆盖 user 参数、连 load_object/include 都一起被拒绝写权限的那个 bug 修好了;本次重新开机复现测试时这 一类报错完全没有再出现(log/debug.log 这次干净到驱动都没建 这个文件),说明它们本来就是同一个已知 bug 在 wabaod 触发路径 下的又一种表现形式,并不是 wabaod 自己独有的问题,无需额外改动。

修复只改了 adm/daemons/wabaod.lpc 一个文件(insert_blank())。 验证:~/src/fluffos/build-debug/src/driver config.fluffos 全新开 机,log/debug.log 全程未生成(零运行期报错,wabaod 的 create() 正常跑完并成功 log_file("wabao", ...) 记下本轮选中的房间);随后 用 scripts/mudclient.py 走完整注册流程(wabaoe/宝藏测试, 密码 test12345,选性别、留邮箱、接受天赋、look/score 确认属 性正常、quit 正常道别扣布衣),并按本项目惯例额外做了一次真正的 断线重连验证:新开一条连接、用刚设的密码登录,成功进入游戏并 look/quit,全程 log/debug.log 仍未产生任何报错。驱动测试 结束后按精确 PID kill,ps -p 确认已退出;测试产生的 data/{login,user}/w/wabaoe.o 存档已删除,不提交。

已清理

(本档案已在此前一轮明确确认与 hy/海洋 血统无关,独立验证出同 一类 log_error/log_file bug 形状,纯属拷贝粘贴模式的巧合,不是同源 血统关系。)

AGENTS.md §7.100 fix (2026-08-19): redundant replace_program(ROOM) landmine

Same corpus-wide bug as the batch-1-6 sweep (ROOM macro "/inherit/room/room" from include/globals.h). Deleted 2,336 live standalone replace_program(ROOM); lines under work/ via fix_710_room.py — matched the survey's live-occurrence count exactly. work/clone/misc/roommaker.lpc does not have the string-builder variant of this bug (no replace_program reference at all in that file), so no manual tool fix was needed here. No .lpc files under work/data/ in this lib, so no false-negative risk. Remaining matches after the fix are all pre-existing //-commented.

Verified: clean build-debug boot (zero new compile errors, zero "cannot replace"/"cannot bind" in debug.log), live admin login (fluffos/Mud@2026, GB-encoding client) into the game world, score/quit worked cleanly (look landed mid-MOTD pagination and just advanced a page — non-issue). Incidental data/{login,user}/f/fluffos.o save drift from the login test was reverted via git checkout HEAD before committing.

§7.30 uninitialized-mapping accessor sweep (2026-08-20)

Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2 via round-four testing): 4 accessor(s) in this file returned a raw never-initialized mapping instance variable (defaults to int 0, not ([]), until first assigned), crashing any unguarded keys()/sizeof()/indexing caller for a fresh/untrained character. Fixed at the accessor level (mapp(x) ? x : ([])) per the documented remedy. Verified via lpcc --batch static compile check only (not a live boot) as part of a large mechanical sweep; not individually functionally re-tested live on this lib.

Round-four §10.7 deep test (2026-08-21): death/respawn gap resolved, clean

Death/respawn — now verified end-to-end, no bugs found

Prior rounds explicitly left death/respawn unverified: the admin account's combat stats were far too strong for the wild dog to pose any real threat. This round closed that gap. A fresh, weak non-admin test character (dsjczi, id-only, password redacted — 膂力19/悟性24/ 根骨19/身法18, 攻击力11/防御力12, freshly registered with no gear or skill training) was registered, then the admin account (fluffos, already-documented credentials, no new secret recorded here) used goto dsjczi followed by the admin call command (call dsjczi->die(), defined in cmds/adm/call.lpc, which does a raw call_other() with no non-wizard-player guard) to force a real, conclusive death — deliberately bypassing only the *combat outcome*, not the death/reincarnation machinery itself, matching this session's established precedent (smash in cmds/wiz/smash.lpc explicitly refuses userp(ob) && !wizardp(ob) targets, so call is the correct tool here, not a design bypass).

Full cycle traced and verified: 1. die() (feature/damage.lpc:115) fired correctly: death message ("试死子口中喷出几口鲜血,倒在地上,死了!"), a corpse object left behind in the room, a "江湖传闻" broadcast, ghost flag set, jing/qi/eff_jing/eff_qi all reset to 1, character moved to DEATH_ROOM = /d/death/gate ("鬼门关"). 2. DEATH_ROOM->start_death(this_object()) is called unconditionally by die() but no file in this lib actually defines a start_death() function reachable from /d/death/gate's inherit chain (grep -rl start_death only turns up the call site itself plus one unrelated NPC). This is a silent no-op (call_other() to a nonexistent function returns 0 with no error, no debug.log entry, no driver rejection) — per this project's standing scope rule, a silent no-op with no error signature is not something to "fix" speculatively, and it turns out to be harmless: the REAL reincarnation trigger is a completely separate mechanism, see next step. 3. Moving into /d/death/gate broadcasts init() to the room's wgargoyle NPC ("白无常", d/death/npc/wgargoyle.lpc), whose own init() schedules a 5-stage call_out("death_stage", 5, ...) interrogation sequence (guarded by a death_stage_active temp flag against reconnect-duplication, per the AGENTS.md §7.112 pattern — already correctly guarded here, see checklist section below). All 5 stages delivered correctly over ~25 seconds (verified via call dsjczi->query_temp("death_stage_active") reading back 0 and call dsjczi->is_ghost() reading back 0 after the sequence completed). 4. Final stage called ob->reincarnate() (feature/damage.lpc:183), which cleared the ghost flag and restored eff_jing/eff_qi to max, then (falling through, by design, into the same function body) dropped all inventory and moved the character to REVIVE_ROOM = /d/city/wumiao ("武庙"). 5. Re-logged in as dsjczi after the full cycle: reconnect banner ("重新连线完毕"), score showed 你共死亡: 1 次 (death counter incremented correctly), character correctly located in 武庙, attack/defense stats visibly reduced post-death (intentional penalty, not a bug), look/quit both worked normally.

log/debug.log stayed clean throughout the entire sequence (checked before, during the ~25s death_stage wait, and after reconnect) — only ordinary first-touch lazy-compile Warning: lines from unrelated objects being loaded for the first time this boot, zero runtime errors, zero driver-level rejections. No bug found or fixed this round — the death/respawn gap flagged by prior rounds is now fully closed with a clean result.

Cleanup: driver killed by exact PID (confirmed via readlink -f /proc/<pid>/cwd first), data/{login,user}/f/fluffos.o timestamp drift reverted via git checkout HEAD, test character dsjczi's save files (data/{login,user}/d/dsjczi.o) deleted (not committed), log/debug.log/log/boot.out removed.

Fast standard-checklist sanity pass (grep + targeted read, all clean or already-fixed)

深度功能测试(2026-09-04,round three,shop + 拜师)

新角度:扬州醉仙楼购物 + 丐帮拜师。2026-08-08 / 2026-08-13 / 2026-08-21 三轮都没测商店和拜师。这是火云录2000(ES/金庸血统),不是 海洋系 的 hy/hy2000/hy5。端口 40162。第一输入是 GB/Big5 选单,发 g, 再英文 id。管理员 fluffos / Mud@2026(中文名云飞,权限 (admin))。 wzd_log.lpc 里 fluffos 白名单已是合法正则 .*,本机无验证码。 cmds/usr/save.lpc 有 300 秒冷却(「请过一会儿再 save」),本轮用 call me->save() 落盘(返回 1)。

和海洋系左全不同:本档 kungfu/class/gaibang/zuo-qu.lpc 的左全只收 已经是丐帮且袋数 ≥ 6 的弟子(「一袋一袋升」)。树洞里真正收新人 的是同房的裘万家(qiu-wan.lpc,经验 < 2000 即可)。醉仙楼下的店小 二是 /kungfu/class/npc/xiaoer.lpc,不是 d/city/npc/xiaoer2.lpc。

实测过程

管理员 fluffos / Mud@2026,落地巫师休息室。身上没钱, clone /clone/money/gold 一次成功(本档 clone 走 log_file("trace/file/clone"),log_file() 已有 assure_file,没复 现 hy2000 那种 /log/cmds 崩溃)。

goto /d/city/zuixianlou。list:烤鸡腿八十文铜板、牛皮酒袋一两白 银、包子五十文铜板、松鼠鳜鱼/冰晶红茶各十两白银。buy jitui 成功 (「你向店小二买下一根烤鸡腿」)。一两黄金换成九十九两银子 + 二十文 铜板 + 鸡腿。feature/dealer.lpc 的 query("vendor_goods") 已经打在 物件自己身上(店小二 init() 也绑了 do_list/do_buy),丐帮拒买 那段是注释掉的。

goto /d/gaibang/inhole,左全和裘万家都在。apprentice zuo 被拒: 「我们丐帮需要一袋一袋升,小兄弟先要从一袋弟子做起。」apprentice qiu 一次成功:恭喜成为丐帮的第二十六代弟子。score 称谓「丐帮一袋 弟子」、师傅裘万家。杀驱动冷启动再登录:称谓/师傅/九十九两银子/二十 文铜板/布袋都在。烤鸡腿未进 autoload。

发现并修复的 PROGRAMMING bug

1. 华山剑宗收徒计数拼写(与 hy/hy2000/hy5 同形,静态对照 修,本轮拜师走的是裘万家不是华山): d/biwu/feng-buping.lpc 的 recruit_apprentice() 写 add("apprentice_availavble", -1),永远减不到 set("apprentice_available", 3) 那个字段。本档华山活路径是 kungfu/class/huashan/yue.lpc / feng.lpc,没有 yue-buqun.lpc, 只有这一处活的拼写错误。

深度功能测试(§10.7,2026-10-04)— negative range ends

scripts/lpc_fix_negative_ranges.py: 4 line(s) in 1 file(s) count a range from the end with < (x[a..-1] -> x[a..<1], x[-2..] -> x[<2..]; KB 06 §7.209). In this driver a negative constant end gave "" / ({ }) and a negative start the whole value, so each of these returned the wrong slice; the compile warning A negative constant as the second element of arr[x..y] is gone from the files that compile. Range lvalues (s[0..-1] = text, the prepend idiom) are left alone. A paired compile of the changed files at HEAD and in the working tree showed no new error.

深度功能测试(§10.7,2026-10-05)— here-document terminators

scripts/lpc_fix_heredoc_terminator.py --all --apply: 1 here-document block(s) repaired (1 with the terminator glued to the last text line, 0 with it indented), so End of file in text block no longer hides the room or object behind them: d/kunlun/ceting_w.lpc. The terminator must start its line (the lexer's own test, KB 04 §6.10); a glued one lost its newline in the GBK -> UTF-8 conversion together with a half character, which stays out.

深度功能测试(§10.7,2026-10-04)— paths named in another case

The archive comes from a case-insensitive host: files are stored as BAGUA0.lpc, longjing.C, d/SHAOLIN/, the code names them in lower case (__DIR__ "bagua0", "tea/longjing", "/d/shaolin/..."), so the rooms, NPCs and items behind them could not be loaded (a .C file is not an .lpc file; KB 03 §4.5). scripts/lpc_case_paths.py --convert --apply hy3: 18 file(s) renamed to lower case (.C -> .lpc, .H -> .h) and 50 path reference(s) in 2 file(s) rewritten to the new spelling; 0 skipped, 0 ambiguous. Load check of the 20 objects that were renamed, edited or name a renamed path (HEAD against the working tree, an object is the same under any spelling of its path): 2 PASS -> 20 PASS, 0 that loaded before fail now, 18 more load.

18 files moved (18 .lpc); mostly under d/death/HELLZhen (18). A rescan with scripts/lpc_warnings.py hy3 is still due: the renamed files are compiled for the first time.

深度功能测试(§10.7,2026-10-05)— room base survives a raising NPC

scripts/lpc_resilient_room.py --apply: make_inventory() of inherit/room/room.lpc loads each inventory object as if (catch(ob = new(file)) || !objectp(ob)) return 0;. new() of a file that is not there returns 0 (the room just lacks that NPC), but new() of a file whose create() raises (a skill file for set_skill() this archive never had, a carry_object() item that is not there, a header that never shipped) raised inside the room and the room did not load at all. The wrong-case renames of this lib (the section above) make the NPCs behind them reachable for the first time, so a room that holds one with such a content gap would have gone from "NPC missing" to "room missing"; now it loads without that NPC, as it did before. The room base compiles and loads with the change (HEAD against the working tree). KB 03 §4.5.

深度功能测试(§10.7,2026-10-05)— 任务表里的 .c 路径与任务守护进程的防护

scripts/lpc_dynamic_quest_guard.py:1 处 spread_quest() 调用(init_dynamic_quest() 的循环里)包进 catch(),缺失的任务物品或编译不过的房间只跳过那一个任务,守护进程照常加载、其余任务照常生成。 验证:改动过的 adm/daemons/questd.lpc 在新进程里加载,HEAD 通过 1 个、工作树通过 1 个(共 1 个),无回退。

深度功能测试(§10.7,2026-10-05)— 房间列出的物件缺档时房间照常加载

房间基类 inherit/room/room.lpc:reset() 的 case 1: 拿到 0 就跳过这一项(if (!objectp(ob[list[i]])) break;);reset() 的 default: 拿到 0 就跳过这一项(if (!objectp(ob[list[i]][j])) continue;)。档案里没有的 NPC 或物品(或 create() 出错的物件)原先会让列出它的房间整个加载失败(Bad argument 1 to environment(),或对 0 的 call_other()),连带这个房间后面的区域;现在房间照常加载,只是少了那个物件,下次 reset() 再试(KB 05 §7.25;scripts/lpc_resilient_room.py、scripts/lpc_room_reset_guard.py)。 验证:探针(scripts/lpc_room_reset_probe.py:房间基类列出一个不存在的物件,再调用 reset())HEAD 单件 崩溃、多件 崩溃,工作树 单件 OK、多件 OK。

深度功能测试(§10.7,2026-10-07)— 空的 if (current_water == 0) {}

3 个房间的 valid_leave() 里有一行什么也不做的 if (current_water == 0) {}(编译警告 Expression has no side effects),删去,行为不变:d/xingxiu/nanjiang2.lpc、d/xingxiu/nanjiang3.lpc、d/xingxiu/shanjiao.lpc。

深度功能测试(§10.7,2026-10-07)— 编译警告整理

scripts/lpc_warnings.py hy3 --fix 加 scripts/lpc_fix_no_effect.py --apply(d/tiezhang 三个房间删去 return 后面的 "\n";,kungfu/skill/xuanyuan-arrow.lpc 删去什么也不做的 (: throw_weapon :); 等),共改动 431 个 .lpc 和若干 .h。HEAD 与工作树分别加载(新进程):401 -> 401 通过,无回退;改过的头文件的 33 个包含者 28 -> 28 通过。adm/single/simul_efun.lpc 单独编译的告警是被包含片段的假象(KB 04 §6.10)。

启动时警告 41 -> 0;新进程登录正常(英文名限 3 到 7 个字母)。

编译警告收尾(2026-10-13)

scripts/toolkit_fix.sh 一轮:18 处 int init() 改 void init(),11 处 if (arg != "a" & arg != "b") 的按位 & 改 &&(两边都是 0/1,结果不变),补两条原型,去掉 1 处多余继承;手工:比武台 d/biwu/biwutai.lpc、d/biwuold/biwu/biwutai.lpc 的 no_die() 改 void(feature/damage.lpc 不读返回值),书库 d/city/library.lpc 的 STORY_DIR 先 #undef,kungfu/skill/huashan-jian.lpc 多余的 ; 删去。能编译的文件警告清零;改动的 40 个对象在 HEAD 与工作树各载入一次:HEAD PASS 39,tree PASS 39,regress 0。

内力/精力当作伤害种类(2026-10-15,KB 06 §7.241 第二类)

本库 feature/damage.lpc 的 receive_damage() 不接受 jingli/neili/force 等种类,me->receive_damage("jingli", 30) 之类在练功、绝招、吸取时报 F_DAMAGE: 伤害种类错误。23 处改为 add(type, -N)(scripts/lpc_fix_damage_calls.py 第二步)。

无门派玩家的 family 映射(2026-10-15,KB 05 §7.30 第三种)

mapping fam = ob->query("family"); 之后直接 fam["family_name"]:没有门派(新人或叛师后)的玩家在学习、练功、拜师、进入门派房间时报 Value being indexed is zero,而不是作者写好的提示。7 处在声明行加上 if (!mapp(fam)) fam = ([ ]);(scripts/lpc_fix_family_guard.py)。

东方故事/西游记体系的技能文件(2026-10-15,KB 06 §7.241 第三类)

这些 kungfu/skill 文件来自 gin/kee/sen/force 体系,本库人物只有 jing/qi/neili:receive_damage("kee", 30) 报 伤害种类错误,query("force") 永远为 0,技能学不了也练不了。按 kee→qi、gin/sen→jing、force→neili、max_force→max_neili、force_factor→jiali 改了属性名(scripts/lpc_port_es_props.py),共 60 个文件。

其他体系的属性名(2026-10-15,KB 06 §7.241 第三类,--any-file)

另有 9 个文件(绝招、状态、物品、NPC 等,不限于 kungfu/skill)来自 gin/kee/sen/force 体系,同样按 kee→qi、gin/sen→jing、force→neili 改名(scripts/lpc_port_es_props.py --any-file)。

family 映射(补)(2026-10-15)

mapping fam = (mapping)me->query("family");(带类型转换的写法)同样直接取下标,1 处补上 if (!mapp(fam)) fam = ([ ]);。

治疗/疗伤的属性名(2026-10-15,KB 06 §7.241)

receive_heal()/receive_curing() 也只接受本库的种类。2 个文件(多为只调用 receive_heal/receive_curing 的药物、NPC)来自其他体系,按本库的属性名改名(scripts/lpc_port_es_props.py --any-file)。

family 映射(再补)(2026-10-15,KB 05 §7.30)

mapping fam; fam = (mapping)ob->query("family");(先声明后赋值)和泥潭式的 query("family", me) 同样直接取下标:无门派的新人拜师(attempt_apprentice/recognize_apprentice)、NPC 的 greeting、房间的 valid_leave、ask_me 等报 Value being indexed is zero。8 处补上 if (!mapp(fam)) fam = ([ ]);(刚 recruit_apprentice() 之后的除外)。

技能按另一门武功的等级取招(2026-10-15,KB 06 §7.243)

这些技能文件是从别的武功复制改名来的,query_action() 仍用原武功的等级查招式表:只会本技能的人等级为 0,取不到招,每次出招都报错。改为读本技能自己的等级(scripts/lpc_fix_action_level.py):chousui-zhang、hy-strike。

空手使用兵器绝招(2026-10-15,KB 06 §7.246)

perform 指令允许直接点名招式(如 perform stick.ban),这些绝招读了 me->query_temp("weapon") 却从不检查,空手时 weapon->name() 报错(有的已先扣了内力)。在赋值后补 if (!objectp(weapon)) return notify_fail("你必须手持兵器才能使用这一招。\n");(scripts/lpc_fix_perform_weapon.py):wuyue-blade/jiao。

把经验、属性、内力当技能读(2026-10-15,KB 06 §7.247)

经验、属性、内力上限不是技能,xkx/ES 的 query_skill() 对它们只返回 0(风云的还会去载入同名技能文件而报错)。改为 query("...")(scripts/lpc_fix_pool_as_skill.py):liancheng-jian/ci、liancheng-jian/erguang(random(me->query_skill("combat_exp")) > target->query_skill("combat_exp") 恒为 0 > 0,这一招永远不成功)。

妙手回春的银针检查(2026-10-15)

miaoshouhuichun 的 valid_learn() 用了未赋值的 object ob,ob->query_temp("weapon") 每次都报错,谁也学不了;还把兵器对象和字符串 "银针" 比较。照 chidi 的修法改为 ob = me->query_temp("weapon"),再用 id("yin zhen")/id("yinzhen") 判断是否银针。

暗器功夫取了 this_player() 的兵器(2026-10-15)

feihua-shou、tangmen-anqi 的 query_action() 用 this_player()->query_temp("weapon") 代替出手者 me 的兵器:NPC 在玩家的回合里出手(反击、进门时 auto_fight 的 call_out)时取到的是玩家的兵器,玩家空手就报错。改为 me->query_temp("weapon"),扣暗器数量前先检查兵器存在。

碧海生潮曲空手报错(2026-10-15,KB 06 §7.246)

iceforce/roar(碧海生潮曲)先 ob = me->query_temp("weapon"),再直接拿 base_name(ob) 判断是不是玉箫;空手 exert roar 时 base_name(0) 报错,提示“你必须先找一只玉萧来才可以吹--曲”根本出不来。条件前补 !objectp(ob) ||。

iceforce「chillgaze」从未编译通过(2026-10-15)

iceforce/chillgaze 原档在第一个 return notify_fail(...) 后多了一个 },exert() 就此结束,后面的语句全落在函数外,skill、damage 也没有声明,文件编译失败,这个 exert 从来用不了。照 bixiecanyang、hc、xyzx3 已修好的版本删去多余的 }、补上 int skill, damage;,其余字句不变,只是缩进进函数体。

技能名拼错(2026-10-15,KB 06 §7.249)

query_skill() 里的技能名拼错了,或用的是本库改名前的旧名;本库没有这个技能,调用永远得 0:门槛(< N 就拒绝)永远过不去,相关功夫或绝招学不了、用不了;内功互斥(> N 就拒绝)从不生效;公式里这一项一直是 0。经汉字名(提示文字或中文名词典)或纯拼写差异(_/-、少一个连字符、相邻字母颠倒)核对后,改为本库的技能名(scripts/lpc_fix_skill_typo.py):beimin-shengong→beiming-shengong(/d/mj/skill/jiuyang-shengong、cha-dao、guiyuan-dafa、honghua-shengong、jiuyang-shengong、qidu-xinjing 等 13 个文件);zhenfen-xinfa→zhenfeng-xinfa(/d/wuguan/skill/zfwy-bu、/d/wuguan/skills/zfwy-bu、/d/wuguan2/skill/zfwy-bu、/d/wuguan2/skills/zfwy-bu);zhenfeng-jian→zhenfeng-jianfa(bisha-jian/sha、zhenfeng-jianfa/feng、zhenfeng-jianfa/hu);shiftforce→shift-force(shiftforce/erase、shiftforce/hitback);mizongxinfa→mizong-xinfa(longxiang/fanchang);yihua-jimu→yihua-jiemu(yihua-jiemu);zixia-shenggong→zixia-shengong(fanliangyi-dao/sanshen)。

柔云步法「柔云纵」有时报错(2026-10-15,KB 06 §7.251)

rouyun-steps/zong 随机把人送到三个房间之一:精、精力已经扣了,“乘云而去了”也说了,送不过去时人留在战斗里并报错。第三个是巫师的测试房 /u/deaner/test1,库里没有;改为 /d/city/guangchang(hy、jym 等库原本就用这个)。

银索金铃「点穴」对空手的对手报错(2026-10-15,KB 06 §7.246)

yinsuo-jinling/dian 失手时三种描写之一是“真气贯注”加对手兵器的名字,对手空手时 ob 为 0,三次失手有一次报错。改为 (objectp(ob) ? ob->query("name") : "全身")(泥潭一系原本就写作“真气贯注全身”)。

family 映射内联取下标(2026-10-15,KB 05 §7.30)

ob->query("family")["master_name"]、me->query("family")["family_name"](泥潭式为 query("family", ob)[...])直接对门派映射取下标:没有门派的人(新玩家、叛师者、大多数 NPC)在 NPC 的打招呼和问话、绝招的门派判断、房间的 valid_leave 里报 Value being indexed is zero,而不是得到拒绝。18 处(15 个文件)改为 dbase 路径查询 query("family/master_name"):有门派时值相同,没有时得 0;原有的判断照常生效(scripts/lpc_fix_family_index.py)。给映射赋值的写法未动。

NPC 带着本库没有的物品,载入失败(2026-10-15,KB 06 §7.73)

13 个文件、20 处在 create() 里 carry_object("<本库没有的文件>")->wear()(或 wield()、set_amount()):carry_object() 得 0,接着的调用报 Bad argument 1 to EFUN call_other(),NPC 根本载入不了,该有它的房间里就少了这个人。多是从别的系统搬来的 NPC 用了原系统的物品路径(最常见:/d/mingjiao/obj/baipao、/u/csy/kunlun/obj/sword、/u/csy/kunlun/obj/cloth)。每处改为 { object carried_ob = carry_object(...); if (carried_ob) carried_ob->wear(); }(scripts/lpc_guard_carry_object.py):NPC 照常出现,只是不带这件东西;文件补回来(或是虚拟对象)照样会带上。载入检查:改动的文件改前能载入 0 个,改后 11 个(11 个原来载入不了),没有退步;其余 2 个另有原因(多为 set_skill() 了本库没有的武功)。

物品清单把名字的第一个字吃掉(2026-10-18,KB 07 §8.1)

inventory、房间的物品列表(feature/move)和部分 look 把同名物品合并计数,键是 query("unit") + short(),只有一件时按 key[2..] 去掉量词。量词是一个汉字,在原来的 GBK 里占 2 字节,[2..] 正好去掉量词;转成 UTF-8 以后一个汉字只占一个下标,这一刀把名字的第一个字也切掉了(「把长剑」只显示「剑」,带颜色的名字切掉的是转义序列开头)。改为 [1..](scripts/lpc_fix_unit_cut.py):cmds/std/look.lpc、cmds/usr/inventory.c.lpc、cmds/usr/inventory.lpc、feature/move.lpc。

去掉的预定义宏 SAVE_EXTENSION(2026-10-18,KB 04 §6.11)

老版 MudOS 给每个 LPC 对象预先定义了 SAVE_EXTENSION(".o");FluffOS 的 ChangeLog(COMPAT_BUSTER 一条)把它删了,改用 __SAVE_EXTENSION__。本库没有自己 #define 这个宏,用到它的文件一律 Undefined variable 'SAVE_EXTENSION',整个对象载入不了。改成 __SAVE_EXTENSION__(scripts/lpc_fix_predefined_macro.py):d/taishan/tang3.lpc。tang3/tang/meng-zhu 是武林盟主一类的 NPC,原来一个都载入不了。改后用 lpcc 逐个载入这些对象:1 个通过。

kungfu/skill/qingyi-jian 第一式的 skill_name 丢了收尾引号(2026-10-18,KB 03 §4.6)

"skill_name" : "大悲式, 的收尾引号没了(转码时跟半个汉字一起丢了),字符串连到下一行,damage_type 成了代码:Illegal character 0xe5,整个武功载入不了。补回 ",(同系的 bixiecanyang、syxjl 等库里有完好的同名文件)。载入:通过。

set_skill() 遇到本库没有文件的武功不再抛错(2026-10-18,KB 06 §7.256)

feature/skill.lpc 里的 set_skill()、map_skill()、prepare_skill() 碰到没有武功文件的名字就 error("F_SKILL: No such skill (…)"),调用它们的 NPC create() 整个中断:NPC 载入不了,刷出它的房间也少一个人。本库有 6 个对象设了本库没有文件的武功(3 个名字,最多的是 yiyang、juehu-shou、xuanxu-daofa)。三处都改成 return:这一门武功不给、不映射,对象照常载入,只是少了它(缺的武功本身仍是内容缺口)。抽样载入这些对象:6 个里 5 个通过,其余 1 个停在别的错误上(job/li:*No program in object '/job/li'!)。(scripts/lpc_guard_set_skill.py)

通向不存在房间的出口,按对面房间的回头出口改正(2026-10-18,KB 06 §7.257)

房间出口 "west": __DIR__"xxx" 指向的文件本库没有,玩家走过去就被卡住(笔误、改过名的房间,或者没带进档案的编号房间)。对面的房间存在、并且它相反方向的出口正好指回这个房间,说明出口原本就是通向它:/d/kunlun/liangong 的 south:sanshengtang → shanshengtang。改动后每个出口都能解析到本库的文件(scripts/lpc_fix_dead_exits.py;目标在运行时本来就能载入的库——虚拟房间——不动)。

补回本库没有的基类文件(2026-10-18,KB 04 §6.15)

下面这些基类本库没有,继承它们的对象(房间、NPC、物品)整批载入不了(inherit XXX; 的宏没定义,或者 inherit "/std/…"; 的文件不在)。同系的库里有同名文件,两库有大量逐字节相同的文件(亲缘关系),所以从那边原样拷来,缺的宏补进全局头文件 include/globals.h:/inherit/sserver(宏 SSERVER)←ldtx,2 个对象继承它,抽样 2/2 载入。每个基类补回后单独载入、再抽样载入使用它的对象,基类载不进来或者一个用户也载不进来的就撤掉(本库撤掉了它们,不再补)。(scripts/lpc_restore_bases.py)

武功名拼错的 NPC(2026-10-19,KB 06 §7.258)

set_skill("kunlun-shnfa", …)、map_skill("dodge", "shaolin-shnfa") 这样的调用把武功名拼错了:本库没有这个武功文件,有的是拼对的那个。以前这种 NPC 在 create() 里报 No such skill 载入不了;武功缺失时跳过之后它们能载入,可是少了那门武功(set_skill 被跳过,map_skill 映射不到,门派弟子用普通轻功/拳脚)。按核对过的对照表改正,共 33 处、33 个文件:kunlun-shnfa→kunlun-shenfa(12 处)、shaolin-shnfa→shaolin-shenfa(10 处)、xinxiu-duzhang→xingxiu-duzhang(2 处)、kongmingquan→kongming-quan(2 处)、shenhuo-shengong→shenghuo-shengong(2 处)、yan-fly→yanfly(2 处)、meinu-quan→meinv-quan(1 处)、snow-step→snowstep(1 处)等共 9 个名字。(scripts/lpc_fix_skill_names.py)

set_name 的 id 参数传成字符串(2026-10-19,KB 06 §7.260)

set_name("海口大碗", "bowl"); 把物品的 id 写成了字符串,本库的 set_name(string name, string *id) 要的是数组,驱动在编译时报 Bad type for argument 2 of set_name ( string * vs string ),整个物件载入不了;旧驱动不检查参数类型,字符串里照样找得到这个词,物品能用 id 称呼。改成 ({ "bowl" }),共 2 个文件:/d/baituo/npc/obj/bowl.lpc、/d/baituo/obj/bowl.lpc。(scripts/lpc_fix_set_name_id.py)

区域物件的零碎修正(2026-10-19,KB 06 §7.267–§7.271)

逐个物件与 HEAD 对比载入,没有退步。

RANK_D 对 0 的称呼(2026-10-19,KB 06 §7.273)

adm/daemons/rankd.lpc 的 query_respect()、query_rude()、query_self()、query_self_rude() 里 4 个函数开头补上 if (!objectp(ob)) ob = this_object();。NPC 在 create() 里写 "…" + RANK_D->query_respect(this_player()) + "…"(inquiry 对话、chat_msg),驱动自己跑 reset() 时没有人在场,this_player() 是 0。旧驱动里 0->query("age") 返回 0,称呼走默认分支;新驱动直接报 Bad argument 1 to EFUN call_other(),房间的 make_inventory() 吞掉错误,被打死的 NPC 再也刷新不回来。用 scripts/lpc_reach_census.py --walk 找到(xkx100 的武当弟子、一灯、汴梁书生…);修在守护程序里,不动 1,800 个 NPC 文件。

被注释吞掉的 inherit / include(2026-10-19,KB 06 §7.274)

/kungfu/skill/liehuo-jian/fen.lpc:#include <ansi.h>。这些指令接在上一行 // 注释的末尾(档案里丢了换行),成了注释的一部分,驱动看不到:缺 inherit 的技能报 Undefined function offensive_target,缺 #include <weapon.h> 的兵器报语法错误。scripts/lpc_fix_swallowed_directive.py 把换行放回去。载入检查 1 个文件,0 个原来编译不过、现在载入,没有退步。

玩家打造兵器模板没有打造者时(2026-10-19,KB 06 §7.275)

/d/quanzhen/npc/obj/m_sword.lpc(共 1 个)的 create() 开头 me = this_player(); 之后无条件读 me->query("weapon/name") 等打造数据。房间刷新时没有人在场(me 为 0),或者 NPC 在别的 NPC 的命令环境里 carry_object() 这个模板(NPC 的 weapon 属性是文件名字符串),旧驱动里读出来是 0 或字符串,switch 照样落到 default;新驱动报 Bad argument 1 to EFUN call_other() / Bad argument 1 to switch,NPC 和它所在的房间载入不了(--walk 普查里一个玩家走进房间就触发)。在 //读入数据 之后加 if (!me || !mapp(me->query("weapon"))) { setup(); return; }:没有打造者就留一个没有名字的空模板,玩家打造的流程不变。

补回丢失的标点(2026-10-19,KB 03 §4.6)

转换时丢掉的分号、逗号、引号或文件末尾的 },共 5 个文件,修前 HEAD 载入失败。别的库里同路径的完好副本只比这里少几个标点,按它补回(括号里是那个库):/kungfu/skill/huang.lpc(bixiecanyang)、/quest/baituo/qlist3.lpc(xyzx3)。一行文字在逗号前丢了结尾的引号(下一行是同一个表的下一项),补上:/kungfu/skill/yanxing-dao.lpc。文件末尾少了 }(最后一个或两个字节丢了),补上:/quest/baobiao/yuanwai.lpc、/u/hsly/cmds/aconvert.lpc。修后与 HEAD 逐个对比载入:这 5 个物件全部载入,没有退步(scripts/lpc_restore_from_twin.py、lpc_fix_eaten_quote.py --comma、lpc_fix_eof_braces.py)。

== !"字符串" 多出来的 !(2026-10-19,KB 06 §7.280)

!"taoist" 是整数 0,x == !"taoist" 就是“x 等于 0”,作者为其余所有人写的那一支永远走不到。具体是:性别检查永远不拦人,男的照样能学玉女心法。全部改成 != "字符串"(scripts/lpc_fix_not_literal_cmp.py):/kungfu/skill/other/yunu-xinfa.lpc(1 处)。同样的行在 xkx 一系的 35 个库里都有。

x != "a" || x != "b" 和 x == "a" && x == "b":同一个值的比较链永远成立/永远不成立(2026-10-20,KB 06 §7.282)

if (arg != "wan" || arg != "丸") return notify_fail(...) 对任何 arg 都为真,dir == "south" && dir == "north" 永远为假:条件下面的守卫要么永远拦、要么永远不拦。作者要的是“既不是 A 也不是 B”(&&)或“是 A 或 B”(||)。!= 链的 || 改成 &&(仅当条件下面是 return 的拒绝/守卫),== 链的 && 改成 ||(scripts/lpc_fix_cmp_chain.py)。改动:/kungfu/skill/kumu-shengong.lpc(2 处)。

call_out_info() 的每一项只有 3 个元素(2026-10-20,KB 06 §7.287)

驱动返回的是 ({ 物件, 函数, 延迟 }),不带 call_out 的参数,旧代码读第 4 项 info[i][3](callouts 指令、calloutd、cod 工具)一读就报 Array index out of bounds,指令从第一行起什么也打印不出来。改为 (sizeof(info[i]) > 3 ? info[i][3] : 0)(scripts/lpc_fix_callout_info.py)。改动:/cmds/wiz/callouts.lpc(1 处)。

if (x = 常量):条件里写成赋值的比较(2026-10-20,KB 06 §7.290)

if (arg = "button" || arg = "按钮")、if (!arg || arg = "") return 0;、else if (check = 0 && tempB != ""):把 == 写成了 =,条件的值就是那个常量,分支对所有非零数和任何字符串(连 "" 都算)永远成立、对 0 永远不成立,变量还被覆盖;驱动对此没有任何警告。每一处 = 改成 ==(scripts/lpc_fix_cond_assign.py,共 8 处)。改动:/d/city4/puke-room.lpc(4 处)、/kungfu/skill/jiuyang-force/roar.lpc(1 处)、/kungfu/skill/jiuyang-shengong/roar.lpc(1 处)、/kungfu/skill/shenghuo-shengong/roar.lpc(1 处)、/kungfu/skill/taiji-shengong/hou.lpc(1 处)。

socket / dumpsocket 指令:dump_socket_status() 驱动里没有(2026-10-20,KB 06 §7.291)

这些巫师指令 write(dump_socket_status());,MudOS 的 efun 在 FluffOS 里不存在,指令编译不过。在模拟 efun 文件里补了 dump_socket_status():用 socket_status() 排出同样的表(没有 sockets 包的构建,比如 WASM,只有表头;scripts/lpc_add_sefun.py dump_socket_status)。

登录密码超过 255 字节:crypt() 抛错(2026-10-20,KB 06 §7.294)

驱动的 crypt() 对超过 255 字节的密钥直接报错(Error in crypt(), check your salt),老驱动则按任意长度散列。在登录提示符下输入 256 字节以上的密码,密码检查那一行就抛错,连线停在一个裸的 > 提示符上,登录走不完(password 指令的旧密码检查同样);用 300 个 x 当参数的扫描发现的。/adm/obj/simul_efun.lpc 里补了一个同名的 simul_efun crypt(key, salt):只有超长的密钥才被截短(先截到 255 个字符,再逐字符截到 sizeof(to_buffer(key)) <= 255,限制按字节算,一个汉字占三个字节),再交给 efun::crypt();普通密码原样散列,已存的密码散列不受影响(scripts/lpc_add_sefun.py crypt)。

翻页器 start_more(read_file(...)):文件缺失时 explode(0)(2026-10-20,KB 06 §7.300)

东方故事系的翻页器 void start_more(string msg) { ... explode(msg, "\n") ... } 被这样调用:start_more(read_file(HELP_DIR + "help/topics"))、start_more(read_file(NEWS))。压缩包没带的文件使 read_file() 回 0,explode(0, ...) 在本驱动里报 Bad argument 1 to explode()(不带参数的 help 指令就是这样出错的),老驱动把 0 当空文本。在 start_more 开头加了 if (!stringp(msg)) return;(scripts/lpc_fix_start_more.py)。改动:/feature/more.lpc。

NPC 的 chat() 在 chat_msg 为空数组时下标越界(2026-10-21,KB 06 §7.334)

NPC 基类的 chat() 是 if (arrayp(msg = query(...))) { if (random(100) < chance) { rnd = random(sizeof(msg)); if (stringp(msg[rnd])) ...,不检查列表是否为空。本库现有的 NPC 文件里没有字面写成空 chat_msg 的(扫描只认 set("chat_msg", ({ })));守卫挡的是运行时才为空的列表和以后新增的 NPC。在 random(100) < chance 前面加 sizeof(msg) &&(scripts/lpc_fix_chat_empty.py;if (random(100) > chance) return 0; 的写法是 !sizeof(msg) ||)。改动:/inherit/char/npc.lpc(共 1 个文件)。

存档里的 .c 文件名改成 .lpc(2026-10-21,KB 03 §4.2 第 9 项)

存档里写着 "/d/city/npc/wei.c" 这样的文件名;extract 时源文件已经全部改成 .lpc,而驱动对带扩展名的路径只认字面,new() / load_object() / move() 都找不到它,调用方多半把失败当成「没有这个东西」悄悄跳过。本库 2 个存档共 13 处按 scripts/lpc_fix_save_dotc.py 改成 .lpc(只改 .lpc 存在而 .c 不存在的字符串;玩家存档、备份、留言板、巫师目录和文件索引缓存不动)。改动:/clone/misc/site.o(12 处)、/d/shaolin/npc/obj/kat.o(1 处)(共 2 个存档)。

blockade / recover:data/keep 不存在,解封之后世界仍然锁着(2026-10-21,KB 06 §7.340)

管理员扫描里 blockade 报 Error copying file from /data/user/f/fluffos.o to /data/keep/fluffos, Error: No such file or directory,随后的 recover 在第一个 cp() 上死于 */data/keep/fluffos: lstat failed,来不及执行最后的 LOGIN_D->set_madlock(0):封锁解不开。data/keep/ 是运行时目录,git 克隆里没有空目录。blockade 在第一次写之前 if (file_size("/data/keep") != -2) mkdir("/data/keep");(mkdir() 失败答 0,不抛错),recover 对没有保存档的玩家 if (file_size(src) < 0) continue;,其余照常恢复、照常解锁(scripts/lpc_fix_keep_dir.py,hy5 上实测:没有保存档时 recover 答“时空解封完毕”,blockade 建出 data/keep 并保存,recover 取回并删除)。改动(3 个文件):/cmds/adm/blockade.lpc、/cmds/adm/recover.lpc、/cmds/adm/recover_sp.lpc。

obj.h.es2:blockade / recover 包含的头文件档案里没有(2026-10-21,KB 04 §6.23)

blockade.lpc、recover*.lpc #include <obj.h.es2>(OBJ_*、NPC_* 路径的 ES2 头文件,hy5、xkx100 等 33 个库带着),本库的 include 目录没有它,这些指令从来编译不了(Cannot #include obj.h.es2),data/keep 的修补也无从生效。指令本身不用里面的宏;从同系的 hy5 复制一份头文件(blockade.lpc 还把 <obj.h.es2> 写成了 <obj.h>,改成与同目录的 recover*.lpc 一致),加载检查 HEAD 与工作树对照:3 个对象原来加载失败,现在通过,没有退步。

selfthinking、qlian:缺乏实战经验的提示读了不存在的老师(2026-10-21,KB 06 §7.348)

自创武功的自习指令在“技能等级³/10 大于实战经验”时打印 printf("也许是缺乏实战经验,你对%s的回答总是无法领会。\n", ob->name())。这一句是从 learn 抄来的,ob 是老师;自习没有老师,object ob; 从没赋值,ob->name() 抛 call_other() ... Got: int(0)。改成 你对「%s」的疑问总是无法领会 加 to_chinese(skillname),去掉没用的 object ob;。改动:/cmds/skill/qlian.lpc、/cmds/skill/selfthinking.lpc。

persuade(渡世济人):ob->query("no_fight") 的 ob 没赋值(2026-10-21,KB 06 §7.348)

峨嵋弟子用 persuade 一律在第三个判断抛错;其余 146 份同类指令写的是 environment(me)->query("no_fight")。这里的 ob 还是后面 call_out("compelete_dushi", 3, me, victim, ob, ..) 传下去的第三个参数(compelete_dushi 没用它),所以在判断前加 ob = environment(me);。改动:/cmds/std/persuade.lpc。

妙手回春 valid_learn():先读 ob->query_temp("weapon") 再给 ob 赋值(2026-10-21,KB 06 §7.348)

学这门暗器技能时 valid_learn() 第一个武器检查读的是没赋值的 ob,xue / learn 在这里抛错;后面 ob = me->query_temp("weapon") 的检查才是对的。有两种写法:if (!ob->query_temp("weapon")) 改成 me->query_temp("weapon");if ((string)ob->query_temp("weapon") != "银针")(拿一个对象和字符串比较,永远不等,补上 ob 之后这门技能也学不成)改成后一种写法里的 !objectp(ob = me->query_temp("weapon")) || !(ob->id("yin zhen") || ob->id("yinzhen"))。改动:/d/city2/shenzhen/skills/miaoshouhuichun.lpc。

注册到不存在函数的 add_action(2026-10-21,KB 06 §7.349)

add_action("函数", "动词") 绑定的函数,在对象本身、它包含的头文件、它继承的父类和继承它的子类里都没有定义(scripts/lpc_scan_callout_targets.py 静态解析,子类用传递闭包复核,scripts/lpc_verify_handlers.py 运行时 function_exists() 复核)。驱动从玩家最新的一条动作往回找,遇到这样的句子就报 *Function for verb 'drop' not found.,同一个动词的其他处理函数不再尝试(不是最新的一条就悄悄跳过)。删除了 65 条注册(50 个文件,scripts/lpc_fix_dead_add_action.py),动词留给别的处理函数:/clone/book/skybook.lpc(cloud_goto)、/clone/music/cd01.lpc(do_start、do_stop)、/clone/music/cd02.lpc(do_start、do_stop)、/clone/music/cd03.lpc(do_start、do_stop)、/clone/music/cd04.lpc(do_start、do_stop)、/clone/music/cd05.lpc(do_start、do_stop)、/clone/music/cd06.lpc(do_start、do_stop)、/clone/music/cd07.lpc(do_start、do_stop)、/clone/music/cd08.lpc(do_start、do_stop)、/clone/music/cd10.lpc(do_start、do_stop) 等共 50 个文件。最多的函数名:do_send 15 处、do_start 13 处、do_stop 13 处、do_decide 8 处、blk_cmds 3 处。

对象路径里的 ..:new(__DIR__ "../obj/x") 报 Read access denied(2026-10-22,KB 06 §7.351)

__DIR__ 是当前文件所在目录(带结尾斜杠),__DIR__ "../obj/x" 就是 /d/zhiye/npc/../obj/x;驱动的 legal_path() 不接受带 .. 的路径,new() / load_object() 直接抛 *Read access denied.(实测,find_object() 对它答 0)。走库自己的 carry_object() / 房间 objects 表的路径,库的基类会先规范化,能用;直接把路径交给 new() / clone_object() / load_object() / move() 的不行,调用到那一步才报错。改成规范化后的绝对路径(scripts/lpc_fix_dotdot_dir.py --direct):/d/lingxiao/npc/yan.lpc(__DIR__ "../laolang" → "/d/lingxiao/laolang"), /d/wudang/npc/xiaocui.lpc(__DIR__ "../obj/nuerxiang" → "/d/wudang/obj/nuerxiang")。

缺失物品的 new() / carry_object() 调用链加了保护(2026-10-22,KB 06 §7.73 补充)

new(路径)->move(...); / carry_object(宏("x"))->wear(); 这类语句,路径指向的文件在这个压缩包里没有:new() 返回 0,->move() 在 0 上报 Bad argument 1 to EFUN call_other()。在 create() 里这个对象永远加载不了,在 reset() 里第一个缺失物品之后的刷新每次 reset 都被跳过。2 个文件里 3 处(new)改成 { object new_ob = new(路径); if (new_ob) new_ob->move(...); }(scripts/lpc_guard_carry_object.py --new:路径按这个文件自己看到的宏解析,宏名冲突、虚拟对象路径一律跳过)。 对这 2 个改动文件做加载检查(HEAD 与工作区对比):HEAD 能加载 1 个,现在 1 个(新增可加载 0 个,回归 0 个)。

调用了、但这个库自己的守护进程里没有的函数(2026-10-22,KB 06 §7.354)

MACRO->函数() 调用的函数在这个库的守护进程里不存在:call_other() 对不存在的函数不报错、只返回 0,所以这些功能(时间显示、昼夜事件、名字检查、价格文字……)一直没起作用。同一血统另一个库的同名守护进程里有这些函数,原文照抄到本库守护进程末尾(scripts/lpc_port_function.py;调用处传的参数个数、函数体用到的函数 / 全局变量 / 宏 / 字符串键都在本库里有,已核对;守护进程在 HEAD 和工作区都能加载,每个函数用固定参数各调用一次:HEAD 返回 0,现在返回正常的值):/adm/daemons/natured.lpc ← aoxiangtianji:room_event_fun()(4 处调用);/adm/daemons/chinesed.lpc ← fengyun434:check_chinese()(5 处调用)。

(: 函数 :) 指针指向对象自己没有定义的函数(2026-10-22,KB 06 §7.355)

item_desc / inquiry / chat_msg_combat 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:编译不报错,用到时驱动报 *Undefined lfun pointer called: 函数名(look 某物、ask NPC about 话题 直接出错,战斗 / 闲聊里的指针在 NPC 的 chat() 里出错,这一拍心跳的后半段被跳过)。scripts/lpc_scan_callout_targets.py --kinds=lfun。 还剩 2 个函数没有补(item_desc 2):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/d/city/ximenroad.lpc:look_gaoshi、/d/yihua/lianhuachi.lpc:look_CAI。

log/ 下的日志子目录没有人建:写日志的 write_file() / log_file() 报错(2026-10-22,KB 06 §7.358)

这个库的代码往 log/ 的 1 个子目录写日志:log/doc/register(cmds/usr/helpbbs.lpc)。压缩包、git clone 和站点包里都没有这些目录(本地启动没有写过它们,gen_keep_dirs.py 没记),write_file() 对不存在的目录抛 *Wrong permissions for opening file /log/dlog/money for append. "No such file or directory",调用它的函数在写日志那一行中断,后面的奖励、标志、步骤都没有执行。本库的 log_file() 会自己建目录(实测,或读源码:nitan 系的 assure_file()),所以这里只记了直接用 write_file() / save_object() 写的目录。把 log/doc/register 记进 scripts/wasm_keep_dirs.txt(scripts/lpc_keep_log_dirs.py;站点和 pristine 树按它建空目录)。证明(scripts/lpcc_eval.py,在 /adm/daemons 这类目录下的求值对象里写 /log/zzdirprobe/...,新进程)见 KB 06 §7.358 的实测表。

(: 函数名 :) 指针指向本库没有的函数:只含这个指针的行加了注释(2026-10-22,KB 06 §7.355 补充)

inquiry / item_desc / chat_msg* 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:用到时(ask、look、NPC 闲聊)驱动抛 *Undefined lfun pointer called: 函数名,这一拍心跳的后半段被跳过。这些函数没有可以补回的来源(别的库同一路径的文件里没有,或者它还要用本库没有的东西),所以 2 个文件里 2 行只含这个指针的行("gaoshi": (: look_gaoshi :), "CAI": (: look_CAI :),)加了注释,原文保留并写明原因,这一项当作没有这个话题 / 物品 / 闲聊条目(scripts/lpc_fix_dangling_lfun.py;#include 的文件在库里缺失的对象、指针不在整行上的写法没动)。 前提(function_exists())和加载检查(HEAD 与工作区对比,本库改动的 .lpc 文件)的结果见 KB 06 §7.355:没有一个回归。

汉字按字节切片的老写法没有换成按字符:改法名 "澄" + name[2..3]、辈分判断 name[0..1] == "澄" 等 36 处(2026-10-22,KB 06 §7.360)

原档按字节算字符串区间(一个汉字 2 字节):name[2..3] 是名字的第二个字,name[0..1] == "澄" 问名字是不是以「澄」开头。转成 UTF-8 之后,这个驱动的区间和 strlen() 都按字符算(strlen("澄观") 是 2,"澄观"[0..1] 是两个字),老算术原样留着、意思全变:拜入少林 / 武当 / 峨嵋等派的玩家被改成错误的法名(二字名 张三 变成一个字的 澄,更长的名字取到第三个字);各派掌门的辈分判断(name[0..1] == "澄")永远不成立。

本库 36 处(29 个文件):拼名字的赋值 27 处、与汉字常量比较 9 处。例:name[2..3] → name[1..1](/d/biwu/da-mo.lpc:152);name[0..1] → name[0..0](/d/emei/npc/wenxu.lpc:90);name[0..3] → name[0..1](/kungfu/class/taohua/huang.lpc:126)。scripts/lpc_fix_gbk_slice.py 把下标按字符重算(社区的 UTF-8 版 xkx100utf8 里就是同样的写法,作对照);没有改的:截断(name = name[0..7],现在最多 8 个字,只是放宽)、ASCII 的区间(fname[0..3] == "room"、ctime(time())[4..19])和上下文看不出是汉字的区间。证明(scripts/lpcc_eval.py,bixiecanyang;其余各库是同一份文本):让澄字辈掌门 attempt_apprentice() 一个名叫「张三」的访客,HEAD 的法名是 慧,改后是 慧三;抽样 28 个库的 HEAD / 工作树加载对比 0 退步。工具不幂等([0..3] 折半得 [0..1],又是对齐区间),改过的文件记在 scripts/gbk_slice_converted.txt,不要重跑。

长度检查按字节写,旁边的提示按汉字写:18 处(2026-10-22,KB 06 §7.362)

老档的 strlen() 数字节(一个汉字 2 字节),转成 UTF-8 后它数字符:提示写「必须是 2 到 6 个中文字」的检查还是 strlen(name) < 4 || strlen(name) > 12,于是两三个字的房名、帮会名、群名、聊天室名、称号被提示自己说允许的那句话拒绝,上限却是提示的两倍;留言板的标题检查 i < 4 || i > 24 || i % 2 还会拒绝所有奇数个字的标题(post 你好吗)。本库 18 处(9 个文件):if ((strlen(name) < 4) || (strlen(name) > 8)) {(/banghui/guandi.lpc:166);if ((strlen(name) < 2) || (strlen(name) > 12)) {(/cmds/skill/creatskill.lpc:618)。scripts/lpc_fix_strlen_gate.py 以提示为准:条件里每个 strlen 门槛都恰是提示所说数字的两倍才折半,存长度的变量(i = strlen(arg);)的门槛和 || i % 2 奇偶项、其后循环的 i % 2 == 0 && 一并处理;提示里有英文 / 字母 / 字节的不动。证明(scripts/lpcc_eval.py,bxsj 的留言板,求值对象继承 NPC 并重写 edit() 记录调用,command("post 标题")):HEAD 拒绝「你好」和「你好吗」、放行 23 个字的标题;改后接受前两个、拒绝第三个;shenmo 的 named.lpc invalid_new_name("张三"):HEAD 回 名字只能是2-4个中文字。,改后回 0。抽样 24 + 15 个库的 HEAD / 工作树加载对比 0 退步。

按字节写的汉字循环、茶馆猜诗和同盟频道标题(2026-10-23,KB 06 §7.363)

老档按字节做「一个汉字」:while (i--) if (i % 2 == 0 && !is_chinese(name[i..<0])) 只检查偶数下标,奇数位上的拉丁字母(张a)会过;茶馆猜诗 mixup() 用 strlen(str)/2 再 j=j+j、str[k..k+1] 交换两字节;泥潭系 channeld 的 switch (strlen(fname)) case 4/6/8/10 和 strlen(family)==4/6 按字节长度给同盟 / 门派名加空格。本驱动的 strlen() 和区间都按字符算。scripts/lpc_fix_byte_char.py:去掉奇偶项、把区间改成 name[i..i],按字符重写 mixup() 并把 strlen(first)>=14 折成 7,频道标题的 case / 门派长度改成字符数(对照 aoxiangtianji)。本库 汉字循环 / is_chinese 区间 11 个文件;茶馆猜诗 mixup 1 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。

血条 / 表情标题按字节算显示宽度(2026-10-23,KB 06 §7.365)

老档把汉字当两字节:bar_string[0..(val * N / max) * 2 - 1] 把「格数」换成字节下标,半格血条在本驱动(按字符算区间)上会整条画满;巫师表情 edemote 的 repeat_string("─", 13 - (strlen(emotion) / 2)) 也会少减汉字宽度。scripts/lpc_fix_display_pad.py:去掉 CJK 血条 / 空白条上的 * 2(jings/qis 赋值和 blank_string3[0..(23-a)] 的 23→11 一并改),表情标题去掉 / 2;ASCII 空格的 none_string / empty_string 仍保留 * 2(一格两个空格)。本库 2 处(1 个文件)。证明(lpcc_eval.py hhsj):tribar_graph(6,9,12) 在 HEAD 画出整条 12 个■,改后为 6 个■+3 个□;麻将 strlen(tempB)/2 是两字符牌码,未改。

Beyond 出口仍指向 /u/beyond(2026-10-23,KB 06 §7.368)

宁波 / 苏州 / 慕容等区域已进 /d/ningbo、/d/suzhou、/d/mr、/d/hz,出口与任务物路径仍写 /u/beyond/…。scripts/lpc_fix_beyond_exits.py 在目标 .lpc 存在时改写(murong→mr)。本库 1 处。证明:sjplii xikou HEAD 西向 /u/beyond/ningbo/aywsi,改后 /d/ningbo/aywsi 可加载;bxsj hubian1 三向均可加载。

死巫师出口 gold/dock、sunrise、mei(2026-10-23,KB 06 §7.370)

/d/wanjiegu/road4 东向 /u/g/gold/dock、峨眉寿星居南向 /u/xinyue/sunrise_room、玩家卧室通往 /u/mei/… 均无对应房间。scripts/lpc_fix_drop_dead_u_exits.py 删除这些出口行,并去掉同方向的 create_door(否则 create_door 无出口会炸)。本库 1 处。证明:zxty08nxgbb 的 road4 HEAD 有东向,改后没有;mei_room1 可加载。

中文名 / 验证码仍按 GBK 取「两字节一字」(2026-10-23,KB 06 §7.373)

pname = pname[(random(sizeof(pname)) & 0xFFFE)..<1]; pname = pname[0..1]; 在按字符计下标时会取出两个汉字。scripts/lpc_fix_pname_slice.py 去掉掩码并把收尾改成 [0..0](pname/pname2/sec_name/str/str1)。本库 4 处。证明:nt1 生成名长度 2–4;HEAD 常见 3–5。

doc/build devil 丢分号/粘连 inherit(2026-10-27,KB 04 §6.25 Also)

doc/build/devil.lpc(建档示例倭寇)被格式化弄坏:inherit NPC void create() 粘在一起,语句之间的 ; 全丢,还有嵌套坏掉的 set("con", set("con", 10)。按原意重写成带 setup() 的完好 NPC(原 /obj/blade、/obj/cloth 在多数库不存在,示例里去掉携带以免 create 炸)。证明:HEAD 加载失败;改后加载成功。

hanbing `random 反引号(2026-10-27,KB 04 §6.25 Also)

hanbing-mianzhang / hanbing-mianzhang2 在 random( 前多了一个反引号,驱动按模板字面量读到 EOF。删掉。证明:HEAD 失败;改后加载。

深度功能测试(2026-10-27,§6.25 ZHAOSHI 截断玩家技能)

玩家自创武功在 // ZHAOSHI : 0 处截断(EOF),无法加载。按同系完整 moming-blade 补一招 + valid_*/query_*/practice(5):kungfu/skill/badknife-sword.lpc, kungfu/skill/wujifinger-finger.lpc, kungfu/skill/zmyzzz-unarmed.lpc, kungfu/skill/wuqing-sword.lpc, kungfu/skill/qimai-finger.lpc。

深度功能测试(2026-10-27,§6.25 zhongling tell_object 引号错位)

d/wanjiegu/npc/zhongling(及同路径副本)的 tell_object("who, 钟灵脱下一双绣花鞋。\n") 把对象参数写进了字符串;改为 tell_object(who, "…")。证明:原文错位;改后加载,语料残渣 0。

深度功能测试(2026-10-27,§6.25 one-arg message_vision)

message_vision("…") 补第二参(me / TP / this_player())。

深度功能测试(2026-10-27,§6.10 未知 pragma save_binary/optimize)

删除本库中 FluffOS 不认的 #pragma save_binary / #pragma optimize… 行。