Knight's Dream

✅ 可玩

侠客梦

xkm

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

▶ 开始游玩 · Play Now

侠客梦与 jym(金庸梦)、xkx2000zxb 同属"侠客行I"这套底层代码库在不同站点的流通版本,共享同一套 `simul_efun` 与太湖古墓、昆仑、少林、武当、峨嵋、丐帮、日月神教、桃花岛等约五十个场景组成的地图骨架;新角色在"侠客岛"的海滩上苏醒,被一位笑呵呵的渔翁迎接,随后才踏入江湖投拜门派、闯荡声名。它最具特色的玩法是一套自定义的装备锻造系统:高等级玩家收集海底"金母"异宝、千年灵木等稀有材料后,可前往"神兵古洞"请传奇铁匠莫邪打造兵刃或防具,经过历练淬炼后再到西域一处仙洞找道士张天师,用刺杀刺客或闯迷宫换来的宝石为装备镶嵌加持;若死亡超过 200 次却仍未攒够五万点阅历,角色会被永久锁死在一间"死亡惩罚室"里。

English

A wuxia MUD from the same "Ode to Gallantry I" codebase lineage as this project's jym (Jin Yong's Dream) and xkx2000zxb -- all three are separately circulating copies of one underlying archive, sharing the same simul_efuns and the same roughly 50-zone map skeleton (Taihu Ancient Tomb, Kunlun, Shaolin, Wudang, Emei, the Beggars' Sect, the Sun-Moon Holy Cult, Peach Blossom Island, and more), though xkm's own registration flow adds two steps unique to this copy -- confirming you've read the "Xiake Meng player code of conduct" and supplying a QQ number -- so its connection sequence should not be assumed identical to jym's. New characters wash up on the beach at Xiakedao ("Isle of the Chivalrous"), greeted by a smiling fisherman, before heading out to join sects and build a reputation. Its standout mechanic is a custom equipment-forging system: high-level players who gather rare materials (a sea-bottom "Golden Mother" relic, thousand-year spirit wood) can commission the legendary smith Mo Ye to forge a weapon or suit of armor at the Mysterious-Weapon Ancient Cave, temper it through training, and pay the Taoist master Zhang Tianshi at a Western-Regions immortal's cave to socket it with gems earned by killing assassins or exploring a maze. Dying more than 200 times without reaching 50,000 combat experience permanently locks a character in a death-penalty room.

README

内容亮点

注册流程

new 触发注册 → BIG5 确认(y/n,任何非 y/yes 都视为 GB)→ 英文 id (3-8 个英文字母)→ 确认创建(y/n)→【“侠客梦”玩家守则】确认(y/n) → 中文名字(2-4 个中文字)→ 管理密码(≥5 字元)→ 确认管理密码 → 普 通密码(≥3 字元,且不能与管理密码相同)→ 确认普通密码 → 天赋接受 (y/n,无需先选 0-4,直接展示随机天赋)→ QQ 号码 → 电子邮件地址 (需 id@address 格式)→ 性别(m/f)。

本次修复的关键 bug

管理员账号 / Admin account

管理员名单存储在 adm/daemons/securityd.lpc 自身的存档文件 data/securityd.o 的 wiz_status/wiz_sites 属性里(与 jym 相同的 机制;wiz_sites 也需要一并设置成 ".*",否则会被"请从登记的地址 使用巫师帐号"拒绝登陆)。

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

在线试玩

https://mudlibs.fluffos.info/xkm/

本地运行

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

游戏端口:40191。

NOTES · 移植与修复记录

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

和金庸梦(jym,147)同一血统/同一套 simul_efun 组成——用同样的方式重新实现了 efun::tail()(§6.2);启动干净。完整 WASM 修复:给 band.lpc 加了本地回环放行;修复了 logind.lpc(create()/make_body())里同样的 seteuid(getuid()) 把 euid 重置掉的 bug;修复了 check_legal_name() 过时的 GBK 字节长度界限(去掉了遗留的 +=128 字节变异,把 is_chinese() 校验改成逐字符);给 securityd.lpc 的 get_status() 加上了防重入编译崩溃保护;修复了 quit.lpc 未加保护的 environment(me) 崩溃;修复了 message.lpc 的 tell_room() exc_target=0 崩溃(AGENTS.md §7.12)。jym 里没有的新 bug:get_id() 会无条件为任何 wiz_level>0 的 id 注册 input_to("get_passwdd",...)——包括一个刚被授予巫师权限、但还没有存档档案的全新账号(正是给管理员播种时的场景)——没有检查存档档案是否存在,也没有 return,导致下一次输入被静默转发进 get_passwdd() 去校验一个从未设置过的密码,永远报"密码错误"并断开连线。已修复为在 file_size(存档文件)>=0 时才注册这个早期呼叫(匹配同一函式后面已有的正确检查),并补上缺失的 return。这是原始存档里真实存在的 bug,不是本次管理员播种过程引入的——任何给一个尚未注册的 id 授予巫师权限的真实部署都会碰到。另外发现注册流程比 jym 手足档案多了一个 QQ 号码提示和一道"玩家守则"y/n 确认步骤——已按 AGENTS.md §8.2 直接读取真实的 input_to() 调用链,而不是假设 jym 的确切发送顺序可以照搬。

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

用新注册的管理员角色(fluffos/浮浮)完整走了一遍侠客岛新手教程: follow long ba 带队依次经过沙滩→小路→迎宾馆→小路2(兵器/防具 NPC)→望海亭(背景介绍 NPC)→瀑布(藏身密道+传功 NPC)→两段甬道→ 大山洞(正殿,龙八半途会强行拉着你走,不用自己一步步移动)。全程无 崩溃,食物/饮水条满格(§8.9 不适用)。

兄弟档案排查:先看了同源档案 jym(147,同一套 simul_efun/adm/ obj 血统)已完成的 §10.7 记录,逐项在 xkm 自己的源码里核实、而不是直 接假设结论可以照搬:

战斗测试:在武当山路(/d/wudang/tyroad4)找到低难度"土匪" (combat_exp 50)NPC,kill tufei 后走完完整回合制战斗(多轮攻防、 "半昏迷状态"提示、倒地起身、最终"挣扎了几下就死了"),死后留下可拾取 的尸体。score 确认经验/阅历/属性正常增长,无异常。战斗过程中一次 kill 指令触发了 /cmds/std/kill.lpc 的一次热编译(未使用局部变量 killer 的编译期 warning,无害,且这是所有档案共享的驱动内建指令文 件,不算 xkm 自己的 bug)。

发现并修复一个此前从未被记录过的新 bug(已写入 AGENTS.md §7.83): 在大山洞读留言板(list → read <N>)时,每一次 read 都会在玩家 自己的连线画面上炸出一条被拦截的运行时错误:*call_other() couldn't find object '/kungfu/condition/boardread'。追查后发现 inherit/misc/bboard.lpc 的 do_read() 本意是"每次读留言给 3 点 chatpts(聊天/灌水积分),但用一个叫 boardread 的 10 拍冷却条件把 连续刷分限制住",可整个 kungfu/condition/ 目录里唯独没有 boardread.lpc 这个条件精灵文件(旁边大约 50 个同类条件精灵,比如 drunk.lpc/sleep.lpc/poisoned.lpc,一个不少,就是漏了这个)。 结果是:apply_condition() 设置的冷却条件在下一次心跳时因为精灵文件 加载不到而被立刻从条件表里删除,冷却从未真正生效——意味着刷 read 可以无限刷 chatpts,而且每次都会往 log/condition.err 里写一条报 错。查看 work/log/condition.err.lpc 发现这个 bug 从 2002 年就存在, 几十个不同的真实玩家账号都触发过,是原始档案里长期存在的真 bug,不 是这次环境转换带来的。已仿照最简单的同类条件精灵 sleep.lpc 的写法 补上 kungfu/condition/boardread.lpc(读秒式倒数到 0 就让调用方回收 掉),在同一个 tmux 会话里重新 read 留言验证过:不再报错,list 显示的未读数正常清零。

门派系统:迎宾馆没有门派接引 NPC,甬道 /d/xiakedao/yongdao3 有 "雪山第十三代弟子 大人物",ask lama about 雪山 能问出完整的雪山派 背景介绍,并提示"想来我们雪山吗?先去大轮寺当喇嘛吧"——真正的拜师流 程在大轮寺(另一张地图),这次深挖没有跨图去把整个拜师流程走完,留 作后续深挖的候选项。

死亡/复活:按 AGENTS.md §7.68(现已收窄到仅 bmxkx2001 适用)的 新纪律,这次没有对 d/death/npc/{bgargoyle,wgargoyle,wgargoyle1}.lpc 里的 if (!ob || !present(ob)) return; 判定做任何改动——没有活体验证 "鬼魂在这份档案里确实无法自行移动"且"确实有其它系统会强行把鬼魂拖 走"这两个前提,就不该套用那个重试补丁,本次也没有时间走一遍真实的死 亡流程来验证这两个前提,所以维持原状。

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

§7.112 跨库扫描修复(无常 NPC 重连触发重复轮回链)

AGENTS.md §7.100 修复(2026-08-19,批次五)

ROOM 基类冗余 replace_program(ROOM); 自崩溃地雷(详见 AGENTS.md §7.100):3176 个房间文件的 create() 里紧跟 inherit ROOM; 之后 都有这一行多余调用,永久设下"待替换"标记,第一次对该房间对象绑 定闭包就会崩溃。这份档案有两处代码生成模板烤了同一个地雷:自带建 房工具 clone/misc/roommaker.lpc,以及帮派堂口建造精灵 adm/daemons/groupd.lpc(各自独立的字符串拼接模板)。另外发现 31 个帮派堂口房间源码文件放在 work/data/group/ 下(真正的 .lpc 源码, 不是存档),扫描脚本默认排除 data/ 目录(为了保护玩家 .o 存档) 误伤了这批文件——针对这个子目录单独关闭排除,手动补上。

修复:脚本化删除所有房间文件里独立成行的 replace_program(ROOM);, 加上两处模板手动摘除字符串拼接片段。git diff --stat:3176 files changed,与预期精确吻合(0 处遗留匹配,全部干净)。

验证:build-debug 驱动真实冷启动,端口 40191 正常监听, debug.log 全程干净。尝试用 README 记录的 fluffos/Mud@2026 登录, 但密码已经和存档里的哈希对不上(用 crypt 校验 password/ad_password 两个字段均不匹配)——和批次二 nt6 记录的同一类账号密码漂移问题。 未触碰玩家存档,也未继续深挖新密码,改为依赖干净冷启动(含失败登 录尝试全程 debug.log 零新增行)作为本次纯机械修复的充分验证证据。

§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.

§7.19 enable_player() reentrancy fix (2026-09-01)

Corpus-wide mechanical fix (AGENTS.md §7.19, Batch F of 6). feature/command.lpc's enable_player() had no reentrancy guard: NPC init()->setup()/reset_me() chains reach enable_player()->enable_commands(), which can synchronously re-invoke the same object's init() (driver docs BUGS note; live-verified mhxy/wuhanzhan precedent), and feature/damage.lpc's revive() / cmds/std/sleep.lpc's wakeup() re-invoke enable_player() while already living(), ruling out a bare living() guard. Fixed with the standard in_enable_player_now true reentrancy flag (mhxy's reference fix). Verified via single-file lpcc --batch PASS.

深度功能测试第三轮 / §10.7 round three (2026-09-03)

新角度:2026-08-05 走过侠客岛新手教程、武当土匪战斗、留言板 read (并修了缺失的 boardread 条件)。当时写明没走完门派拜师(只在甬道 问了雪山背景),也没测商店。死亡/复活仍未现场走完。本轮只补商店 + 拜师 + quit/重连,不重打土匪。

登录

README 写的 fluffos / Mud@2026 在 2026-08-19 的 §7.100 机械验证 里已经对不上存档哈希(密码漂移)。本轮复现:同一密码当场「密码错误!」。 在角色未在线时把 data/login/f/fluffos.o 的 password / ad_password 重新写成 Mud@2026 的 SHA-512 crypt,之后登录恢复为 (admin) 浮浮, 落地 /d/xiakedao/shatan。登录后 news 是分页器——后续指令会被当成 翻页,要先 q。

商店(扬州打铁铺)

goto /d/city/datiepu。王铁匠 list 列出菜刀 30 文、铁棒、长剑等。 身上只有布衣和信用卡、没有现钱;buy caidao 因 id 是 cai dao 回 「你想买的东西我这里没有。」clone 一两黄金后 buy cai dao 成交: 「你从王铁匠那里买下了一柄菜刀。」sell cai dao:「你卖掉了一柄菜 刀给王铁匠。」无崩溃。编译警告(dealer.lpc 未使用局部变量)只打给 巫师,不是新 bug。

拜师

2026-08-05 提示的雪山大人物 darba 的 attempt_apprentice() 是 「法王可不允许我收徒」、recruit 被注释掉,是设计拒绝。改走星宿 摘星子(/kungfu/class/xingxiu/zhaixing,几乎无门槛):clone 后 bai zhaixing →「好吧,我就收下你了。」→ 星宿派第三代弟子,师父 摘星子。quit 后重连 score 仍是星宿派。

本轮未发现新的编程 bug

log_file() 在这份档案的 adm/simul_efun/file.lpc 里已被注释掉, clone 没有踩到 fqyy2/sje 那种 /log/nosave 权限抛错。debug.log (libs/xkm/log/debug.log,开机后 mtime 对得上)无 error: / Wrong permissions。死亡/复活、大轮寺雪山拜师仍未测。

本轮修改的文件

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

scripts/lpc_fix_negative_ranges.py: 5 line(s) in 2 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-04)— compile-warning and load-failure pass (ported from xkx2001)

scripts/lpc_warnings.py xkm: 305 distinct diagnostics at the end, 10215 files compile and 196 do not. A load check of every .lpc (10487 files, 700 per VM boot) at HEAD and in the working tree: 10176 PASS -> 10207 PASS, no file that loaded before fails now. 1487 files changed. The code is the xkx2001 root's, so the pass is its pass (libs/xkx2001/NOTES.md has every class, the typos found through the no-side-effects list and the list of files left alone): lpc_twin_port.py adopt xkx2001 xkm carried the fixes of the files whose code is the root's, then lpc_warnings.py --fix, lpc_diamonds.py --fix-redundant, lpc_fix_void_override.py, lpc_fix_macro_redef.py, lpc_fix_prototype_types.py, lpc_move_decl.py, lpc_fix_no_effect.py, lpc_fix_heredoc_terminator.py and (after a rescan) lpc_name_winner.py handled the diagnostics that depend on this lib's own files.

Fixed by hand in this lib (each read first; nothing written new): clone/board/news_b.lpc (do_discard() was string and returned its messages as strings, so the newsdel command never printed them and always reported success: int, notify_fail(), write() and return 1); d/city/qiyuan{2,3,4}.lpc (lost closing quote of set("short", "棋室);; the splice that ports the root's fix refused these three files because the pre-image has an unterminated string); d/murong/obj/qingxin-san.lpc (the credit line by beyond outside a comment); and adm/simul_efun/message.lpc got the message_combatd() alias (KB 04 §6.2).

What is left: the files that do not load in the root either, the wizard directories (/u/program, /u/bright, /u/puma), d/minjiao/ (a second, broken copy of d/mingjiao), the jobold/jobaa/obj1 copies of the job files, d/murong/npc/murong-fu.lpc (its where.h never shipped), and d/heimuya/basket.lpc (an ITEM that calls ::reset() and the undefined check_trigger()).

深度功能测试(§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 xkm: 29 file(s) renamed to lower case (.C -> .lpc, .H -> .h) and 0 path reference(s) in 0 file(s) rewritten to the new spelling; 0 skipped, 0 ambiguous. Load check of the 36 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): 7 PASS -> 27 PASS, 0 that loaded before fail now, 20 more load.

30 files moved (the 29 of the first run, then d/lingjiu/BAGUA.H -> bagua.h once the include resolution of the tool was fixed; the load check above ran before that last rename): the Lingjiu array (bagua.lpc, bagua0-7.lpc, bagua.h), dadao3-4, damen2, gudi, hubian ... of d/lingjiu, d/REGIONS.h -> regions.h. Rescan: 297 distinct diagnostics, 10219 files compile and 192 do not (10215 / 196 / 305 before); the eight bagua* rooms compile after the last rename (checked individually).

深度功能测试(§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-11):“无副作用表达式”警告复查(批 4)

深度功能测试(§10.7,2026-10-11):dns_master 空 if

深度功能测试(§10.7,2026-10-11):dns_master 空 if

深度功能测试(§10.7,2026-10-11):“无副作用表达式”警告复查(二)

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

手工清零;改动的 8 个对象在 HEAD 与工作树各载入一次:HEAD PASS 7,tree PASS 7,regress 0。

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

本库 feature/damage.lpc 的 receive_damage() 不接受 jingli/neili/force 等种类,me->receive_damage("jingli", 30) 之类在练功、绝招、吸取时报 F_DAMAGE: 伤害种类错误。1 处改为 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,而不是作者写好的提示。4 处在声明行加上 if (!mapp(fam)) fam = ([ ]);(scripts/lpc_fix_family_guard.py)。

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

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

内力/上限当作伤害种类(补)(2026-10-15)

victim->receive_wound("force", n, me)(兵器吸内力)、receive_damage("max_qi", random(100))(走火入魔扣上限)等本库不接受的种类,19 处改为 add(type, -N)。

message_vision(msg, environment(me), me)(2026-10-15,KB 06 §7.242)

把房间当成了动作者:message_vision() 取房间的 name() 得 0,replace_string(msg, "$N", 0) 报错。在状态(中毒)里,这个错误发生在 apply_condition(name, duration - 1) 之前,状态永不结束,心跳里后面的恢复也每次被跳过。改为 message_vision(msg, me):/kungfu/condition/laugh、/kungfu/condition/sanpoison、/kungfu/condition/xianglu-du。

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。6 处补上 if (!mapp(fam)) fam = ([ ]);(刚 recruit_apprentice() 之后的除外)。

空手使用兵器绝招(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):dagou-bang/ban、dagou-bang/chan、dagou-bang/chuo、dagou-bang/pi、dagou-bang/sansha、dagou-bang/tiao、dagou-bang/yin、damo-jian/weituo、huashan-jianfa/feilong、huashan-jianfa/san、huashan-jianfa/yijian、jingang-chu/wushang 等 27 个。

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

经验、属性、内力上限不是技能,xkx/ES 的 query_skill() 对它们只返回 0(风云的还会去载入同名技能文件而报错)。改为 query("...")(scripts/lpc_fix_pool_as_skill.py):驯马的 /d/dali/npc/mafu(成功率少了福缘一项)。

临济庄 remove 没有运功时报错(2026-10-15)

linji-zhuang/remove 直接 switch (lj_exert["name"]),lj_exert 是 query_temp("lj_exert");没有正在运用的临济庄功夫时它是 0,exert remove 每次都报 Value being indexed is zero。补上 if (!mapp(lj_exert)) return notify_fail(...)。本库的临济庄各 exert 都不设置 lj_exert,所以这个 exert 以前每次都报错,现在只会提示没有在运功。

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

query_skill() 里的技能名拼错了,或用的是本库改名前的旧名;本库没有这个技能,调用永远得 0:门槛(< N 就拒绝)永远过不去,相关功夫或绝招学不了、用不了;内功互斥(> N 就拒绝)从不生效;公式里这一项一直是 0。经汉字名(提示文字或中文名词典)或纯拼写差异(_/-、少一个连字符、相邻字母颠倒)核对后,改为本库的技能名(scripts/lpc_fix_skill_typo.py):shenhuo-xuanming→shenghuo-xuanming(/d/minjiao/skill/dafeng-yunfei、dafeng-yunfei、xiaoyao-zhangfa);douzhuan-xignyi→douzhuan-xingyi(/d/murong/obj/shu1);jinhse-jianfa→jinshe-jianfa(jinshe-jianfa/jinshe);xiatian-gong→xiantian-gong(/d/zhongnan/skill/chunyang-quan)。

嵩山剑法「蓄力」没穿布衣时报错(2026-10-15)

songshan-jian/xuli 用 cloth = me->query_temp("armor/cloth") 取衣服,随后直接 cloth->query("material") 判断要不要显示“衣袖鼓起”的描写;身上没有布衣时(裸身或只穿铠甲)这里报错,而此时 apply/speed 已经扣掉、复原的 call_out 还没排上,身法就一直少了一截。两处判断前补 objectp(cloth) &&。

技能名拼错:技能文件里拼错自己的名字(2026-10-15,KB 06 §7.249)

技能自己的文件(或它的绝招目录)里,query_skill() 读的是差一个字母的自己的名字,永远得 0:“基本功夫要高过本技能”之类的限制从不生效,按等级取招、计算伤害的那一项一直是 0。改为本技能的名字(scripts/lpc_fix_skill_typo.py 的 self 判据):baitao-xuangong→bitao-xuangong(bitao-xuangong)。

地图数据库 mapdb 的空档防护(2026-10-15,KB 06 §7.250)

genmap 第一次载入时 if (!restore()) save(); 会在地图建好之前写出只有文件头的 data/npc/map.o;mapdb 读它成功后 map 为 0,所有查询都对 0 取下标(nitan170911、shenzhou 等 10 个库就带着这样的文件)。没有 map.o 时 query_random_room_path() 又对空数组取下标。mapdb(/clone/obj/mapdb.lpc)加一个 restore():读档后 map 不是映射就重置为 ([]);地图为空时 query_random_room_path() 返回 0。

随机取房间后不判断就过滤(2026-10-15,KB 06 §7.250)

/d/city/npc/ftb_zhu.lpc、/d/dali/npc/jiumozhi.lpc、/d/qilian/obj/jinhe.lpc 从 mapdb 随机取一个房间后直接 strsrch(room_path, ...) 排除区域;地图还没生成时取回的是 0,strsrch(0, ...) 报错,护镖等任务就此中断。条件前补 !stringp(room_path) ||,取不到房间时走原有的重试和“cannot find target room”提示。

临济庄「幽冥桩」的两处笔误(2026-10-15,KB 06 §7.245、§7.250)

linji-zhuang/youming:killer->querry(...)、me->querry(...) 调用的是不存在的函数,永远得 0,恶人比值只按 PK 数算,改为 query;visit_room() 先拿 range 作判断、后从参数里取 range,判断时它还是 0,效果遇到没载入的房间就停,两行取值挪到前面。

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

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

npc_setup 的浮点截断警告(2026-10-15,KB 04 §6.10)

/clone/obj/cl_npc_setup.lpc、/clone/obj/npc_setup.lpc、/clone/obj1/npc_setup.lpc:level = pow(10 * exp, 0.333334); 把浮点数隐式截成整数,编译时警告;改为 to_int(...),结果不变。

地图档 map.o 读不出来(2026-10-15,KB 03 §4.4)

data/npc/map.o 里三个“棋室”房间(/d/city/qiyuan2~qiyuan4)的 short 少了右引号:原档在“棋室”后有一个孤立的 GBK 前导字节,转码(iconv -c)把它和后面的引号一起丢了。restore_object() 报 Illegal mapping format,mapdb 一直载入失败,用到地图的护镖、jinhe、鸠摩智等都报错。补上三个引号,1512 个房间全部读回;backup/ 下 25 份同样的旧档按 raw/ 原档重新转码。

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,而不是得到拒绝。4 处(3 个文件)改为 dbase 路径查询 query("family/master_name"):有门派时值相同,没有时得 0;原有的判断照常生效(scripts/lpc_fix_family_index.py)。给映射赋值的写法未动。

用兵器的绝招空手施展时报错(内联写法)(2026-10-15,KB 06 §7.246)

绝招不存兵器变量,直接写 (me->query_temp("weapon"))->query("name")(或在拒绝判断里写 (weapon = me->query_temp("weapon"))->query("skill_type")),之前又没检查兵器:空手 perform 时报 Bad argument 1 to EFUN call_other(),内力等往往已经扣掉。在第一次用到它的那条语句前补上“你必须手持兵器才能使用这一招”的拒绝(scripts/lpc_fix_perform_weapon.py):duanyun-bian/duanyun、feiyu-bian/chanrao、jingang-chu/xiangmo、riyue-bian/xumi、yunu-jianfa/suxin。

移进不存在的巫师房间(2026-10-15,KB 06 §7.251)

用完的物品、要“离开”的 NPC、掷在空中的兵器被移进巫师的工作室(/u/aln/、/u/ryu/、/u/wsky/),本库没有这些房间。本库的 move() 用 call_other(dest, "???") 载入目的地,找不到文件就报 call_other() couldn't find object,后面的语句都不执行:药(人参、狐狸皮,clone/drug/cb_renshen、clone/drug/hulipi)吃下后药效已经生效,随后报错:call_out("destroy", 31) 没有排上,药一直留在身上,药效过去后可以再吃;逍遥三笑散(d/xingxiu/npc/obj/sanxiao)弹出之后报错,毒药留在身上,可以一再使用;天山杖法「飞杖」(kungfu/skill/tianshan-zhang/feizhang):杖“撞到山石上断成无数截”之后报错,杖仍留在身上。4 个文件改为移进本库的虚空房间 VOID_OB(/clone/misc/void),与原作把它们“停放”在巫师房间的用意相同。

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

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

补回丢掉的基类宏(2026-10-18,KB 04 §6.13)

inherit F_XXX; 里的宏本库任何头文件都没有定义,报 syntax error, unexpected L_IDENTIFIER, expecting L_STRING or '(',整个对象载入不了;宏指向的基类文件本库其实有,别的库都把这个宏定义成同一个路径。在全局头文件 include/globals.h 里补上:HALBERD → /inherit/weapon/halberd(4 个文件)。(scripts/lpc_restore_macros.py)改后用 lpcc 逐个载入这些对象:4 个里 4 个通过。

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 载入不了,刷出它的房间也少一个人。本库有 19 个对象设了本库没有文件的武功(21 个名字,最多的是 xuantian-wuji、taxue-wuhen、xunlei-jian)。三处都改成 return:这一门武功不给、不映射,对象照常载入,只是少了它(缺的武功本身仍是内容缺口)。抽样载入这些对象:19 个里 18 个通过,其余 1 个停在别的错误上(d/murong/npc/murong-fu:*No program in object '/d/murong/npc/murong-fu'!)。(scripts/lpc_guard_set_skill.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 映射不到,门派弟子用普通轻功/拳脚)。按核对过的对照表改正,共 22 处、19 个文件:lingji-zhuang→linji-zhuang(7 处)、dashouyin→dashou-yin(6 处)、pudu-chang→pudu-zhang(2 处)、stuff→staff(1 处)、huagu-mainzhang→huagu-mianzhang(1 处)、banrou-zhang→banruo-zhang(1 处)、qiankundanuoyi→qiankun-danuoyi(1 处)、jingding-zhang→jinding-zhang(1 处)等共 10 个名字。(scripts/lpc_fix_skill_names.py)

出口指向不存在的房间(2026-10-19,KB 06 §7.257)

下列房间的出口写的文件不存在,而对面恰好只有一个房间的出口指回本房间,所以按对面的房间改正(笔误、大小写、路径少了一级):

改后房间照常载入(与 HEAD 逐个对比,没有退步),出口现在指向存在的房间。

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

adm/daemons/rankd.lpc 的 query_respect()、query_rude()、query_self()、query_self_rude() 里 6 个函数开头补上 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 文件。

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

/d/weapon/weapon/m_blade.lpc、/d/weapon/weapon/m_club.lpc、/d/weapon/weapon/m_hammer.lpc、/d/weapon/weapon/m_staff.lpc、/d/weapon/weapon/m_sword.lpc、/d/weapon/weapon/m_whip.lpc(共 6 个)的 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; }:没有打造者就留一个没有名字的空模板,玩家打造的流程不变。

x == "a" || "b":后面的字符串常量永远为真(2026-10-19,KB 06 §7.281)

if (arg == "yuyou" || "yu you") 里的 "yu you" 是非空字符串,永远为真,整个条件对任何 arg 都成立;作者要的是每个字符串都和变量比较。在每个字符串前补上变量和运算符(scripts/lpc_fix_literal_or.py;forrest2.lpc 是 dir == "north" && "south",手工改成 (dir == "north" || dir == "south") && ...):/d/bwdh/biwu.lpc(1 处)、/d/city/npc/obj/xitie.lpc(2 处)、/d/gaibang/ml.h(1 处)、/d/ruzhou/npc/obj/xitie.lpc(1 处)。

比较链的人工修正(2026-10-20,KB 06 §7.282)

d/hangzhou/huagang1.lpc:挖泥的判断 arg != "泥" || arg != "mud" 永远为真,随便挖什么词都挖出湿泥,后面的“你要挖什么?”走不到;本意是参数是“泥”或 mud 时才挖,改成 == 和 ||。

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,共 28 处)。改动:/d/city/jiuguan2.lpc(2 处)、/d/city/npc/mj.lpc(3 处)、/d/city/npc/mjxiaosi.lpc(3 处)、/d/city/wumiao.lpc(1 处)、/d/city/zuixianlou.lpc(1 处)、/d/heimuya/jiudian.lpc(1 处)、/d/lingshedao/maowu.lpc(1 处)、/d/lingshedao/woshi.lpc(1 处)、/d/minjiao/luanshiduibak.lpc(2 处)、/d/quanzhou/qzkedian.lpc(1 处)、/d/quanzhou/wglou1.lpc(1 处)、/d/xiakedao/no_pk_room.lpc(1 处) 等 15 个文件。

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

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

sefun cat():缺文件时 write(0) 报错(2026-10-20,KB 06 §7.297)

void cat(string file) { write(read_file(file)); }:文件不存在(压缩包没带的欢迎/公告文件,或只有运行中的 mud 才会写的日志)时 read_file() 回 0,write(0) 在本驱动里报 Bad argument 1 to receive(),调用者(登录对话、cat 指令)被中断;老驱动什么也不打印。改成 write(read_file(file) || "");(scripts/lpc_fix_cat_unchecked.py)。改动:/adm/simul_efun/file.lpc。

巫师命令不带参数时对 0 调用 efun(2026-10-21,KB 06 §7.336)

巫师(管理员)把命令敲成不带参数时,驱动把 0 传给字符串参数;下面的命令第一句就把这个 0 交给 efun,运行时报 Bad argument 1 to ...,这条指令从来没有用过。用 scripts/lpcc_bare.py 不登录、在一次 lpcc 求值里以 0 调用 main() 逐个确认后,由 scripts/lpc_fix_bare_arg.py 在第一处使用参数的语句前加守卫:文件自带 int help(object me) 的,守卫是 if (!arg) return help(me);(help() 定义在 main() 之后的 1 个文件补了原型 int help(object me);,否则编译报 Undefined function help)。改动(1 个文件,括号里是接住 0 的 efun):/cmds/arch/test.lpc(present)。加载检查 HEAD 与工作树对照,没有退步。

拼错的 call_out() / input_to() 目标(KB 06 §7.349,2026-10-21)

计时器或输入提示给驱动的函数名和文件里定义的差一个字母;驱动对不存在的函数静默不理,所以对应的计时从来没有触发过。调用和配套的 remove_call_out() 改成已定义的拼法:药炉:burning2 / burning3 → 文件里定义的 buring2 / buring3;do_destroy → 文件里定义的 do_destory。改动:/d/huanghe/npc/tc_wang.lpc、/d/xingxiu/npc/obj/yaolu.lpc、/d/xingxiu/obj/yaolu.lpc。

保护任务的商人 clone/obj/job/job_protect_npc.lpc:两处笔误让整个文件从来没编译过(2026-10-21,KB 04 §6.29)

clone/obj/job/protect.h(保护商人的任务)克隆这个 NPC,但文件有两处笔误:int baohu(string age) 的函数体用的是 arg(Undefined variable 'arg'),而 init() 登记的是 do_baohu,函数名也对不上;query->("id") 多了一个 ->。改成 int do_baohu(string arg) 和 query("id")(if (!player = find_player(...)) 报的 Illegal LHS 只是前面语法错误引出来的连锁错误,这种写法本身是对的,没有动);文件第一次能编译后带出 7 个 Unused local variable 警告(sacrifice、exp_rate、skill_rate、lmt、menpai、killer、kill_num),按 KB 04 §6.10 删掉。baohu / protect 两个动词现在有处理函数,任务的商人也第一次能出现。改动:/clone/obj/job/job_protect_npc.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.,同一个动词的其他处理函数不再尝试(不是最新的一条就悄悄跳过)。删除了 30 条注册(15 个文件,scripts/lpc_fix_dead_add_action.py),动词留给别的处理函数:/d/beijing/obj/kuanglu.lpc(do_look)、/d/m_weapon/npc/jia.lpc(do_levelup)、/d/minjiao/npc/mingjiao_npc.lpc(do_qingjiao)、/d/murong/mrjob/mrnpc/mr_obj/mr_lingpai.lpc(do_zhuo)、/d/murong/shuichi.lpc(do_strike)、/d/murong/shuteng.lpc(do_insert)、/d/quanzhou/npc/gongping-zi.lpc(do_bihua、do_halt)、/d/shenlong/obj/sg_mianzhao.lpc(do_open)、/d/xiakedao/obj/car.lpc(do_hire)、/d/xingxiu/npc/feng.lpc(do_ketou) 等共 15 个文件。最多的函数名:do_bihua 3 处、do_qingjiao 2 处、do_strike 2 处、do_halt 2 处、do_hire 2 处。没有动(读过):/clone/obj/job/job_protect_npc.lpc 的 do_baohu(对象本身编译不过,登记留着,等对象能加载再处理)、/clone/obj/jobold/job_protect_npc.lpc 的 do_baohu(对象本身编译不过,登记留着,等对象能加载再处理)、/clone/obj1/job/job_protect_npc.lpc 的 do_baohu(对象本身编译不过,登记留着,等对象能加载再处理)。

基类的 add_action 登记:处理函数只在后代里定义,基类自己被加载时报错(2026-10-21,KB 06 §7.349)

房间、NPC、公告板这类基类,init() 里登记的 add_action("函数", "动词") 的函数只由继承它的后代定义;基类对象自己被直接加载(房间可以走进去、NPC 可以克隆)时,访客输入这个动词,驱动报 *Function for verb 'x' not found.(第一轮扫描把这些当成“有后代定义,是活的”放过了,scripts/lpc_verify_handlers.py 在基类对象上跑 function_exists() 才看出来)。登记前加 if (function_exists("函数", this_object(), 1))(第三个参数 1:默认 function_exists() 把 protected / private 函数当作没有定义),后代照常登记。共 6 处、1 个文件(scripts/lpc_fix_dead_add_action.py --guard):/d/bwdh/kantai.lpc(do_abandon、do_practice、do_study)。

对象路径里的 ..: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/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 都被跳过。1 个文件里 1 处(new)改成 { object new_ob = new(路径); if (new_ob) new_ob->move(...); }(scripts/lpc_guard_carry_object.py --new:路径按这个文件自己看到的宏解析,宏名冲突、虚拟对象路径一律跳过)。 对这 1 个改动文件做加载检查(HEAD 与工作区对比):HEAD 能加载 1 个,现在 1 个(新增可加载 0 个,回归 0 个)。

(: 函数 :) 指针指向对象自己没有定义的函数(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。 还剩 12 个函数没有补(inquiry 7, chat_msg_combat 5):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/d/city/npc/hua_girl.lpc:ask_me、/d/emei/npc/guide.lpc:ask_job_begin、/d/emei/npc/guide.lpc:ask_job_finish、/d/huanghe/npc/tc_hu.lpc:ask_job、/d/huanghe/npc/tc_you.lpc:ask_join、/d/murong/npc/murong-fu.lpc:ask_baochou、/d/shaolin/npc/xuanci.lpc:ask_tiaoshui、/d/xiakedao/npc/huang.lpc:auto_perform、/d/xiakedao/npc/laozu.lpc:auto_perform、/kungfu/class/shenlong/pang.lpc:auto_perform 等另外 2 个。 另有 2 处函数体被作者整段注释掉(指针没跟着删),是有意关掉的,没动。

运行期目录 log/nosave 不存在,写日志的 write_file() 直接报错(2026-10-22,KB 03 §4.3 补充)

这个库的 9 个文件里有 17 处 write_file("/log/nosave/...") / log_file("nosave/...")(static 改 nosave 时连字符串里的日志路径一起改了,原来是 log/static/):nosave/PURGE、nosave/CRASHES、/log/nosave/LASTCRASH 等。压缩包和站点包里没有这个目录,write_file() 在目录不存在时抛 *Wrong permissions for opening file /log/nosave/... for append. "No such file or directory",调用它的函数(杀人记录、重启记录、call 日志……)当场中断。把 log/nosave 记进 scripts/wasm_keep_dirs.txt(站点和 pristine 树都按它建空目录);没有把字符串改回 static。证明(scripts/lpcc_eval.py,catch(write_file("/log/nosave/ZZTEST", ...)),fqyy2 / hy5 / bmxkx2001 的新进程):补目录前报上面的错误,补后写成功。

不带前导斜杠的物品路径:缺失物品的 new() / carry_object() 调用链加了保护(2026-10-22,KB 06 §7.73 补充)

carry_object("d/city/obj/jiasha")->wear(); 这类路径不带前导斜杠的写法在这个驱动里按根目录解析(new("d/city/obj/changjian") 能加载 /d/city/obj/changjian),所以和带斜杠的一样:文件不在压缩包里时 new() 返回 0,->wear() 在 0 上报 Bad argument 1 to EFUN call_other(),整个 NPC 加载不了。此前的保护工具把这种写法当作「相对当前目录,没法判断」跳过了。1 个文件里 1 处(clone/cloth/cloth)改成带保护的块(scripts/lpc_guard_carry_object.py)。 对这 1 个改动文件做加载检查(HEAD 与工作区对比):HEAD 能加载 0 个,现在 1 个(新增可加载 1 个,回归 0 个)。

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

这个库的代码往 log/ 的 1 个子目录写日志:log/beijing(d/beijing/helper.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() 是 write_file(LOG_DIR + file, text),目录不存在就抛同样的错误(实测)。把 log/beijing 记进 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: 函数名,这一拍心跳的后半段被跳过。这些函数没有可以补回的来源(别的库同一路径的文件里没有,或者它还要用本库没有的东西),所以 11 个文件里 14 行只含这个指针的行("song": (: ask_me :), "治病": (: ask_me :), "zhibing": (: ask_me :),)加了注释,原文保留并写明原因,这一项当作没有这个话题 / 物品 / 闲聊条目(scripts/lpc_fix_dangling_lfun.py;#include 的文件在库里缺失的对象、指针不在整行上的写法没动)。 前提(function_exists())和加载检查(HEAD 与工作区对比,本库改动的 .lpc 文件)的结果见 KB 06 §7.355:没有一个回归。

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

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

本库 118 处(50 个文件):拼名字的赋值 92 处、与汉字常量比较 25 处、改名官的长度检查 1 处。例:name[0..01] → name[0..0](/clone/npc/qiu.lpc:287);name[4..5] → name[2..2](/clone/npc/qiu.lpc:287);name[0..3] → name[0..1](/d/city/npc/shiye.lpc:144)。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,不要重跑。

长度检查按字节写,旁边的提示按汉字写:2 处(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 你好吗)。本库 2 处(1 个文件):if ((strlen(name) < 4) || (strlen(name) > 16)) {(/cmds/group/gbuild.lpc:88)。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 区间 2 个文件。证明(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(一格两个空格)。本库 3 处(1 个文件)。证明(lpcc_eval.py hhsj):tribar_graph(6,9,12) 在 HEAD 画出整条 12 个■,改后为 6 个■+3 个□;麻将 strlen(tempB)/2 是两字符牌码,未改。

/open/ 上残留的全真改名切片(2026-10-23,KB 06 §7.360 Also)

与 §7.360 Also 同源:open/qiu.lpc attempt_apprentice 的 name[0..01] + "志" + name[4..5] → name[0..0] + "志" + name[2..2]。证明:lpcc_eval 「张三丰」HEAD「张三志」、改后「张志丰」。

/open/ 上残留的中文名长度门(2026-10-23,KB 06 §7.362 Also)

lpc_fix_strlen_gate.py 曾把 /open/ 当巫师家跳过。open/logind.lpc check_legal_name:消息写「1 到 4 个中文字」却用 < 2 / > 8 / || i % 2(字节门)。SKIP 去掉 open;并教会在 strlen() 门已折半时去掉 || i % 2(原先只在 i </i > 形上剥奇偶)。证明:lpcc_eval HEAD 拒「王」、改后接受;「王小明五六」两边都拒。循环里的 j % 2 == 0 && is_chinese(name[j..j+1]) 留给 byte_char。

/open/ 上残留的中文名奇偶循环(2026-10-23,KB 06 §7.363 Also)

接 §7.362 Also:open/logind.lpc check_legal_name 循环仍是 j % 2 == 0 && !is_chinese(name[j..j+1])(按字节跳格)。lpc_fix_byte_char.py SKIP 去掉 open → !is_chinese(name[j..j])。拒绝路径已注释,只改高位;证明:对「张a」HEAD 循环命中 0 次、改后命中 1 次(检出拉丁字母「a」)。

find 缺 sefun message_system(2026-10-27,KB 04 §6.16 Also)

cmds/adm/find.lpc 调用 message_system(...),但 adm/simul_efun/message.lpc 没有定义(同系 jym 有:message("system", ..., users(), 0))。对象无法编译。在 notify_fail 前补上同形函数。证明:HEAD 加载失败;改后加载成功。

段延庆 yanqing 无法加载(2026-10-27,KB 04 §6.25 Also)

kungfu/class/dali/yanqing.lpc(jym 为 class_all)attempt_apprentice:query("PKS) 缺收尾引号、query_respect(ob) 无 ob、recruit 后嵌套第二个 void init() 未闭合函数。按 pkuxkx:补引号、ob→me、return 闭合,并把叛师检查并入第一个 init()。jym 另有 !==→!=。证明:HEAD 加载失败;改后加载成功。

深度功能测试(2026-10-27,§6.25 bare set("long" 残渣)

u/snow/new/specialroom:inherit room → ROOM,short/long 补引号。

深度功能测试(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… 行。