Rhapsody Realm II

✅ 可玩

狂想空间II

kxkjii2

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

▶ 开始游玩 · Play Now

ES II/Annihilator 系架构衍生的 mudlib,和 jyqxc 系列不是同一血统(存档用驱动原生的明文格式,不是那一系的旧式二进制格式)。角色创建走互动式点数分配:膂力/定力/悟性/胆识/根骨/灵性/容貌共 7 项从共享的 160 点数池里手动分配,第 8 项"福缘"由剩余点数自动填入。地图以新手区"雪村"(钱庄、当铺、客栈、药铺)起步,主线之外另有一片"过去时空"区域(水烟阁、山坡小径、青石官道)。权限体系比常规多一级,`(manager)` 是比 `(admin)` 更高的顶层职称,档案里两个内置管理员账号都是这个级别。与本项目的 `kxkj`("狂想空间")相比,`diff` 核对确认两者的 `master.lpc`、`securityd.lpc` 及整个死亡区目录逐字节完全相同——不是改编或续作关系,而是同一份 2002 年台湾巫师 wade 发布源码的两份独立存档快照,各自独立搭建了内容不同的同名"雪村"新手区,档案总数仅差 10 个(均为运行期存档差异,非源码)。

English

A mudlib derived from the ES II/Annihilator architecture line, a different lineage from the jyqxc family (it uses the driver's native plaintext save format rather than that family's old binary format). Character creation is a fully interactive point-buy: seven stats (strength, willpower, comprehension, courage, bone structure, spirituality, appearance) hand-allocated from a shared 160-point pool, with an eighth stat, "fortune," auto-filled from whatever is left. Beyond the newbie "Snow Village" zone (pawnshops, inns, a pharmacy) the map extends into a "bygone era" region (a smoke pavilion, hillside paths, a flagstone official road) outside the main storyline. Its rank system adds a tier above the usual top rank — "(manager)" outranks "(admin)" and is held by the archive's two built-in admin accounts. A diff against this project's kxkj (#036, "Rhapsody Realm") shows byte-identical master.lpc, securityd.lpc, and death-system files — not an adaptation or sequel, but another independent snapshot of the same 2002 release by Taiwanese wizard wade, differing by only about 10 runtime files. Each archive independently built its own newbie zone under the shared name "Snow Village," with different actual content — evidence of two separately built instances of the same engine source rather than one being derived from the other.

README

内容亮点

注册流程

英文名字(3-10 个小写英文字母)→ 确认建立新角色(y/n)→ 中文名字 (1-6 个中文字)→ 密码(至少 5 位)→ 确认密码 → 电子邮件地址 → 性别(m/f)→ 互动式天赋分配(膂力→定力→悟性→胆识→根骨→灵性→容 貌,共 7 项手动输入,总点数池 160 点,每项合法范围 10-30;第 8 项 「福缘」由剩余点数自动填入,不再单独询问)→ 按 Enter 键继续 → 进 入游戏世界。

本次修复的关键 bug

1. 358 个文件用了尖括号绝对路径 #include(例如 #include </open/open.h>)。本驱动把尖括号 include 解释成「相 对于 include 目录」而不是「相对于 mudlib 根目录」,这些绝对路径 一个都解析不了。文件数量太多,不适合逐一手改,改用 AGENTS.md §6.1 记载的批量解法:在 master.lpc 加一个 include_file(compiled, from, path) apply,对以 / 开头的 路径前面再多加一个 /,逼driver走跟带引号 include 一样的 merge() 路径解析逻辑——一次修好,不用碰任何一个原始文件。 2. adm/daemons/natured.lpc 的 check_heart_beat() 里有一个 多打的分号,让一个 if 判断式提前结束,变成一句空语句,导致后 面那句原本应该被这个 if 保护的 "/adm/daemons/temp.lpc"->record_heart_beat(...) 变成每秒都会 无条件执行一次——而这个 /adm/daemons/temp.lpc 档案在整个档案 里根本不存在(应该是开发时期的调试用 daemon,发布时被拿掉但呼 叫点没有清干净)。确认过整个仓库都没有这个档案后,直接移除了两 处呼叫,而不是凭空补一个档案出来。

管理员账号 / Admin account

这个 lib 的权限体系里 (manager) 是比 (admin) 更高的一级,管理 员名单里原本两个条目(chen、wun)都是 (manager),所以新增的 fluffos 账号也用了同一级别,存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常注册流程创建,已在游戏内确认 "目前权限 -> (manager)" 显示正确。

此前的账号记录曾标注密码为 Mud2026Adm,但存档核实(§10.7 深度
测试)发现 adm/etc/wizlist 虽有 fluffos (manager) 一行,
data/login/f/ 下却从未真正生成过 fluffos.o 存档——权限名单
曾被单独播种,账号本身从未走过注册流程。已用标准 fluffos/
Mud@2026 组合重新完整注册,标准密码本身可正常使用。另注意:本
档案的账号存档只在真正的 socket 断线(非 quit 指令)时才落
盘,用 kill 结束驱动进程前务必先正常断线,否则未落盘的账号会
"凭空消失"。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。

本地运行

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

游戏端口:40160。

NOTES · 移植与修复记录

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

ES II/Annihilator 衍生的 mudlib(狂想空间II,"Wild Imagination Space II"),和 jyqxc 家族是不同的血统(存档用驱动原生的明文格式,不是那种旧式二进制编码)。修复了两个 bug:(1)358 个档案用了 AGENTS.md §6.1 类的尖括号绝对路径 #include(例如 #include </open/open.h>),这个驱动会把它解析成相对于配置好的 include 目录而不是 mudlib 根目录——因为分散得太多,不适合逐一手改,改用了文档记载的批量解法:在 master.lpc 里加一个 include_file(compiled, from, path) apply,给看起来是绝对路径的 <> include 前面多加一个"/",逼它走和带引号 include 相同的、基于 merge() 的路径解析。(2)adm/daemons/natured.lpc 的 check_heart_beat() 里有一个多余的分号提前终止了一个 if 条件(if (wizardp(...) && ...);),导致后面那句原本应该被这个 if 保护的、对不存在的精灵 /adm/daemons/temp.lpc 的 call_other() 变成每次心跳(每秒,永远)都会无条件执行——确认过这个档案在整个代码库里从来不存在(一个被剪掉的开发/调试用暂存精灵,两处呼叫点从没清理干净);已直接移除这两处死呼叫点,而不是凭空捏造一个替代精灵。注册流程用的是一套特别的互动式点数分配(7 项明确询问的属性、从共享的 160 点数池里分配,第 8 项由剩余点数自动填入),不是 jyqxc 家族那种"自动生成后接受"的模式。这里的管理员等级惯例是 (manager),比 (admin) 高一级——已把 fluffos 播种为 (manager),匹配既有的两个条目。完整的注册→look→score→quit 流程和管理员流程在排版格式化前后都验证过;格式化工具还原了 6 个真正损坏的档案(中文字符密集的字符串字面量里出现了错误的"\ n"分词——这是一种 jyqxc 家族里没见过的新损坏形态,和那个家族的 ASCII 地图压缩模式不同)。有几个 diff 特别大的档案(删掉了几千行)经确认是格式化工具正确地清理掉了几千行原本就存在的尾随空行,不是损坏。

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

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

血统确认:与 kxkj 同一份代码,非"改编"关系

kxkjii2(本档案,089 号)与 kxkj(036 号,本 session 早前已完成 §10.7 深度测试,结论"deep functional test,no programming bugs found")的 adm/obj/master.lpc 主体、adm/daemons/securityd.lpc 逐字节完全相同(diff 输出为空,除去两边各自独立打的 WASM 阶段 #include/compile_error 补丁);work/ 目录树结构、open/death/ 整个死亡区(start.lpc、bridge1-3.lpc、gate.lpc、gateway.lpc、 road1-3.lpc 等)逐文件字节完全相同;档案总数仅差 10 个文件(均为 运行期存档差异,非源码)。结论:这不是"狂想空间"改编或衍生的 "II"续作,而是同一份 2002 年台湾巫师 wade 发布源码的另一份独立快照/ 存档,与本档案自己 README 已有的"和 dfgsiiv13b 的雪村同名但内容不 同——应是各自独立搭建"判断相印证(雪村内容确实独立,但引擎/核心代码 是同一份)。这次比对方式:直接 diff 两份 work/ 下的核心精灵文 件与整个 open/death/ 目录,而非仅凭档案名或简介推测。

管理员账号:README 记录与实际存档不符,已重新播种

README 此前记录的 fluffos/Mud2026Adm/(manager) 虽然 adm/etc/ wizlist 里确实有一行 fluffos (manager),但 work/data/{login, user}/f/ 下翻遍都没有对应的 fluffos.o 存档——说明上一轮只写了权 限名单,从未真正走过注册流程创建账号。本次用标准 fluffos/ Mud@2026 组合重新走了一遍正常注册流程(英文 id → y 确认 → 中文名 "浮浮" → 密码×2 → 邮箱 → 性别 → 7 项天赋各分配 20 点,第 8 项福缘 自动补满),目前权限 -> 【天帝】(manager) 立即生效。额外发现并 确认的存档时机细节:本档案的 LOGIN 对象(含密码的账号存档)既 不在 quit 指令路径写盘,也不在注册完成时写盘,只有真正的 socket 断线(net_dead())才会写——这点与 kxkj 已有 NOTES 记录的现象一 致。第一次用 kill <driver pid> 结束驱动进程时验证到这一点:重启 后 data/login/f/ 目录为空,fluffos 账号"凭空消失",被迫重新注 册;第二次改用正常 telnet 断线(结束 tmux 会话,触发真实 TCP FIN/RST)后确认 data/login/f/fluffos.o 正确落盘,且用标准密码 Mud@2026 成功重新连线("重新连线完毕。"),(manager) 权限保留。 密码沿用项目标准 Mud@2026,未被拒绝,无需变体密码。

核心发现并已修复:死亡后唯一的"复活"出口是死代码,此前每一次死亡都是无法恢复的死局

用 (manager) 账号在 d/snow/eroad2(雪村,与 kxkj 完全同一房间) 对 野狗(非会说话生物,走真杀分支)使用 fight dog,走完完整的 真实死亡流程("你死了" → 送往 阴曹入口),debug.log 全程干净, 无任何报错——死亡本身完全正常,问题出在复活出口。

open/death/start.lpc(阴曹入口)的 exits 映射只有 "north" 一个活 key,"up"/"south" 两行被注释掉;但同一文件的 valid_leave() 紧接着就有这两个方向完整可用的逻辑("south" 是 "你真的想回家吗"的 5-9 次随机重试门槛,"up" 才是真正的复活: reincarnate() + move() 回到人间,打印"恭禧你又重回人世了")。 本档案共用的 cmds/std/go.lpc 在呼叫 valid_leave() 之前先检查方 向是否是 exits 映射里的一个 key(undefinedp(exit[arg]) 直接 return 0),所以 "south"/"up" 这两条分支从来没有被真正执行 过——玩家打 south/up 得到的是"什么? south? 请用 help cmds 查询 指令。",和真正不存在的指令一模一样。已在 open/death/start.lpc 里把这两行注释还原(详见 AGENTS.md §7.101,新增条目)。已在 kxkj 上核对同一档案,确认逐字节相同、同样命中此 bug、本次未修 (留给下次触碰 kxkj 时同步)。

现场验证(修复前 → 修复后对照): 1. 修复前:阴曹入口 处 look 只列出 north 一个出口;打 south/up/stand 全部得到"什么? xxx? 请用 help cmds 查询 指令。"。沿仅有的 north 出口一路走到底(bridge1→bridge2→ bridge3→鬼门关→酆都城门→鬼门大道),发现这整条支线本身也是 未完成内容:open/death/road3.lpc 的房间描述原文是"路的尽头 ..... 还没想到 ...."(原作者自己留下的占位文字),且 open/death/gate.lpc 一旦向北经过就永久拒绝向南返回("进了鬼 门关就别想回去了!")——这条支线一旦被误闯,除了管理员 goto/transfer 或 suicide -n/-f(自毁角色)之外没有任何 出路。鉴于这条支线是原作者明显未完成的探索型旁支内容(非死亡 恢复的必经之路),本次判定为超出"程序 bug"修复范围的既有设计 /未完成内容,只记录不改动。 2. 用 update /open/death/start 热重载后,look 显示三个出口 up、north、south;连续 south 6 次后出现"你真的那么想回 家吗? 好吧!!就如你所愿"门槛消息;up 立即触发完整复活: "突然天中降下一团祥光,令人无法用肉眼直视。过了一会儿,祥光散 去,一道人影出现,你终于从阴间偷跑回来了。",落地新手入门房, score 确认属性/气血/食物饮水全部正常。重启驱动(完整冷启动而 非仅 update)后二次复验,行为一致。

与 §7.68/§7.76 的区别(明确排除,非同一形状):本档案确实也有 经典的 wgargoyle.lpc/bgargoyle.lpc(白无常/黑无常) present(ob) 门控 call_out("death_stage", ...) 五阶段对话链(位 于 鬼门关/酆都城门),且 wgargoyle.lpc 的 init() 正确地对 wizardp(previous_object()) 做了排除(管理员角色路过不会触发这条 链,符合本项目已确认的既有惯例,未见异常)。但本条修复的根因与这 条对话链完全无关——是 阴曹入口(死亡后第一站)的移动指令被共用 派工器在方向未列入 exits 前直接拒绝,valid_leave() 根本没有机 会执行,不是 present() 检查落空或链条被中断。

已知 bug 类别逐项核对(除上述新发现外)

额外顺手修复:master.lpc 把编译警告当错误广播给玩家(对齐 kxkj 已有修法)

kxkj(同代码血统)的 master.lpc 早前已经把 log_error() 里的 efun::write("编译时段错误:" + message) 改成只在 message 不含 "warning:" 时才广播;kxkjii2 这份存档没有这个过滤,导致注册/ 装备/进房间等任何触发懒编译的操作都会把内部档名、行号、"Unused local variable"级别的无害警告原样刷给正在连线的普通玩家。已在 kxkjii2 自己的 master.lpc 里补上同样的过滤(保留写日志,只是不 再广播警告级别的消息)。现场验证:重启驱动后重新注册一次 fluffos,整个注册流程不再出现任何"编译时段错误:"前缀的警告刷 屏,功能行为不变(真正的编译错误仍会照常广播,未测试到真错误场 景,逻辑与 kxkj 完全对齐)。

测试覆盖小结

注册(含账号丢失重建、密码变更核实)→ look/score → enter 正 式进世界 → 移动(新手房→狂想空间入口处→中央驿站→雪村黄土小径,管 理员 goto 快速定位)→ 留言板 post/look board → 战斗 (fight dog,真实杀伤分支)→ 完整死亡 → 复活出口 bug 定位与修复 → 修复后完整复活链路复验(含冷启动后二次复验)→ 清理测试残留 (death_record 测试行、data/board/start_b.o 测试留言、 data/clan.o 的例行序列化 mtime 变动均已用 git checkout 还原, 不纳入本次提交)→ 正常 telnet 断线以确保账号存档落盘。

§7.100 跨库扫描修复(ROOM 基类同款 replace_program() 致命形状)

``§7.112`` residual-gap closure (2026-08-20)

Corpus re-scan (grep -rl 'call_out("death_stage"' ... | filter for missing guard) found unguarded init()-scheduled death_stage() call_out chain(s) in open/death/npc/bgargoyle.lpc, open/death/npc/wgargoyle.lpc that the original two-wave sweep (see AGENTS.md §7.112) missed -- same reconnect-triggered duplicate-chain bug, different filename/lineage. Added the standard query_temp("death_stage_active")/set_temp/delete_temp re-entry guard, adapted per file's own exit points. Compile-verified via lpcc --batch.

§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): 3 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.

Ported §10.7 go.lpc/clan fixes from sibling kxkj (2026-08-21)

cmds/std/go.lpc, cmds/adm/update_dir.lpc, cmds/imm/{ls,lstree}.lpc, cmds/clan/c_create.lpc, and adm/daemons/cland.lpc all confirmed byte-identical (md5sum) to kxkj's pre-fix copies. kxkj's round-four §10.7 deep test found 4 real bugs:

1. go.lpc's .lpc-suffix check sliced only the last 2 characters against the 4-character literal ".lpc", so it never matched and always appended .lpc -- including to paths that already had it. Since the exits mapping is held by reference, this permanently and cumulatively corrupted any room's exit whose destination lacked a literal .lpc suffix in source, breaking that exit for every player after the first use until reboot -- a severe navigation-corrupting bug. Same copy/paste bug in update_dir.lpc (made that admin recompile tool a total no-op) and cosmetically in ls.lpc/lstree.lpc (wrong file-type coloring). 2. c_create.lpc called CLANV_D->create_clanv(), which doesn't exist on the live daemon -- the silent undefined-function no-op meant a clan founder's own clan/name property was never set. 3. cland.lpc's clan_query() lacked the undefinedp() guard its sibling clan_set() has, crashing c_list with "Value being indexed is zero" under a specific directory/data-entry mismatch.

Ported all fixes directly from kxkj's fixed files rather than re-deriving them. Compile-verified via lpcc --batch (not independently live-boot-tested on this lib -- the fixes were already proven live on kxkj).

§10.7 shop purchase + sect apprenticeship (2026-08-24) -- both clean, no bugs found

Two gaps flagged as never tested in this lib's history: buy at a SHOP-type store, and apprentice (拜师) at an NPC sect master. Live-boot tested with the (manager) fluffos account (real telnet disconnect afterward, save residue reverted via git checkout -- this run only touched money/family/inventory scratch state, no persistent account change was intended).

Shop purchase (/open/center/room/store.lpc, 中央驿站商店): this lib's only SHOP-type stock (std/room/shop.lpc) starts genuinely empty (sells = ([])) -- there's no seeded starting inventory anywhere in the two SHOP-inheriting rooms found (store.lpc, open/magic-manor/town/town20.lpc); stock is populated entirely by players sell-ing items to the shop first, which the shop then resells. This is a real design (matches do_list's own "在这你可以 买到" empty-until-stocked framing), not a bug. Tested the full cycle with a cloned /open/main/obj/sword.lpc (base value 400): sell sword -> correctly priced at trade-skill-adjusted (int)(400/400* (300+trade_lv)) = 301 (三银一文钱), item appears in list priced at face value 400 (四两银子) as expected. buy sword first correctly failed ("你身上没有足够的钱币买东西") when the player's cash (301) was less than the buy-side price v/100*(230-trade_lv) = 916; after topping up with a cloned gold coin (10301 total), buy sword succeeded, charged exactly 916 (九银十六文钱), left correct change (9385 = 九十三两银子 + 八十五文钱), moved the sword into inventory, and removed the now-fully-bought-out entry from list/sells. All change/inventory math checked out exactly; no crash, no double-spend, no stock-count mismatch.

Sect apprenticeship (apprentice / cmds/std/apprentice.lpc + feature/apprentice.lpc): checked this lib's apprentice.lpc against the AGENTS.md §7.117 "did you betray your old sect" pattern (unguarded family_name string comparison rejecting first-time applicants with no family yet) before testing live -- this file does not have that shape. Its only prior-membership check is if (me->query("family")) { ... "决定背叛师门" ... } (a plain existence check, correctly falsy for a fresh character with no family set yet), so it was never a §7.117 candidate and needed no fix. Live test: joined the fighter class (join, near open/snow/npc/master_liu.lpc/雪苍派 in 雪苍紫云宝殿, /open/snow/room/room2), then apprentice master liu -> NPC's attempt_apprentice() checked class match (fighter) and str >= 20 (both satisfied by a fresh character's defaults), immediately recruit-ed the player with no rejection or betrayal-check false positive. score afterward correctly showed 雪苍派第五代弟子 (5th-generation disciple) and 师父: 刘全书 (master: Liu Quanshu) -- family/title assignment and generation-number formatting all correct.

No programming bugs found in either area; both are clean. ~90 tool calls for this session (boot, both playthroughs, code review, cleanup).

AGENTS.md §7.19 sweep (2026-09-01): enable_player() reentrancy from init()

Same corpus-wide bug class as mhxy/wuhanzhan (AGENTS.md §7.19), and byte-near-identical to the sibling fix on kxkj: this lib's feature/command.lpc enable_player() wrapper (around the raw enable_commands() efun) is reachable from an NPC's init() via a redundant create()-then-init()-calls-setup()/reset_me() chain -- confirmed via a body-aware static scan of every init() in this lib: 6 NPC files call setup()/reset_me() from init() (e.g. d/snow/npc/waiter.lpc and the open/gblade/npc/pker*.lpc family), after create() already made the object living(). Calling enable_commands() a second time on an already-living() object makes the driver re-invoke that object's own init() as a side effect, re-entering the same chain while the original call is still on the stack -- genuine reentrancy, crashing with "Too deep recursion" (most likely on an NPC's first-ever preload/compile).

feature/damage.lpc's revive() calls enable_player() again while the object is still living(). This confirms a bare if (living(this_object())) return; guard would be the WRONG fix -- used the same true reentrancy-flag fix as mhxy instead: a nosave private int in_enable_player_now; set for the duration of the wrapper's body, guarding only genuine same-call-stack reentrancy while leaving the legitimate revive re-enable unaffected. enable_player() had a pre-existing early return, if (!this_object()) return;, right at the top -- added in_enable_player_now = 0; before that return too (rewritten as a 2-line block) alongside the fall-through exit at the end. Verified via a single-file lpcc --batch compile check (PASS) -- not individually live-boot-tested.

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

scripts/lpc_fix_negative_ranges.py: 21 line(s) in 10 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)— <../x.h> includes resolve: 32 more files load

35 files (the open/start/ areas and the like) include a header named relative to themselves in angle brackets (#include <../start.h>). The driver refuses .. in a <...> name, so they died with Cannot #include. The master's include_file() already turned an absolute <...> name into a quoted-style one; it now does the same for a name that starts ../ ("./" + path; KB 04 §6.1). lpcc --batch loads 33 of the 36 files that carry such an include (HEAD: 1); the 3 that still fail are open/start/room/bad{2,3,4}.lpc, whose ../badman.h is not in the archive. The newly loading files carry warnings of the classes the rest of the lib has (stray Big5 backslashes, unused locals, greeting() return types): the lib's warnings pass has not been done.

深度功能测试(§10.7,2026-10-04)— stray backslash before a closing quote

A Big5 character whose second byte is 0x5C was written with one extra backslash after it (the old driver read 5C 5C as one backslash and so completed the character) and the UTF-8 conversion kept it (KB 03 §4.4). Before a closing quote it escapes the quote, the string runs into the next line and the file does not compile. scripts/lpc_fix_big5_quote_backslash.py deletes it when the character before it encodes to cp950 with 0x5C as second byte and the quote ends an expression. Here: open/scholar/room/newplan/npc/guard8.lpc and data/autoload/scholar/secret_book.lpc, the same two files as in kxkj.

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

scripts/lpc_fix_heredoc_terminator.py --all --apply: 5 here-document block(s) repaired (3 with the terminator glued to the last text line, 2 with it indented), so End of file in text block no longer hides the room or object behind them: open/capital/wind-rain.org/obj/bird-blade.lpc, open/capital/obj/bird-blade.lpc, open/capital/room/king/kr4-5.lpc, open/prayer/room/westarea/t.lpc, open/prayer/room/uhen/16.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 kxkjii2: 14 file(s) renamed to lower case (.C -> .lpc, .H -> .h) and 26 path reference(s) in 22 file(s) rewritten to the new spelling; 0 skipped, 0 ambiguous. Load check of the 60 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): 46 PASS -> 60 PASS, 0 that loaded before fail now, 14 more load.

14 files moved (13 .lpc, 1 .C); mostly under open/main/room (13), open/killer/home (1). A rescan with scripts/lpc_warnings.py kxkjii2 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 std/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)— tail() simul_efun

scripts/lpc_add_tail.py --apply: cmds/apr/tail.lpc calls tail(file), an efun of the MudOS this archive ran on that FluffOS does not have (Undefined function tail: the command did not compile). adm/simul_efun/file.lpc now defines void tail(string file): the last 10 lines of the file, written to the player. Load check (HEAD against the working tree): 1 of the 1 tail command file(s) failed to load at HEAD, all load now, and the simul_efun file loads. KB 04 §6.2.

深度功能测试(§10.7,2026-10-07)— 兵器的 actions 函数指针

set("actions", (: WEAPON_D, "query_action" :));:旧 MudOS 把 (: 字符串, "函数" :) 当作 call_other 函数指针,本驱动把它当作表达式函数指针,求值只得到字符串 "query_action"。没有对应兵器技能时 feature/attack.lpc 直接用兵器的 actions,COMBAT_D 拿到的不是 mapping,reset_action() 后仍不是,记一条 bad action 就不出招——拿着这些兵器打不出攻击。改成别的兵器早已用的 (: call_other, WEAPON_D, "query_action" :)(KB 04 §6.10):std/weapon/throwing.lpc、std/weapon/stick.lpc、std/weapon/whip.lpc、std/weapon/sword.lpc、std/weapon/lance.lpc、std/weapon/arrow.lpc、等共 13 个。改动的文件在 HEAD 与工作树分别加载(新进程),无回退。

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

先用 scripts/lpc_twin_port.py adopt kxkj kxkjii2 把 kxkj 警告整理提交(13b6c22f0aa)里的改动搬到 1737 个修改前与它一致的文件(逐文件核对非 ASCII 文字:除 kxkj 自己删掉的以外没有丢失或改动),其中包括四把兵器的 (: __FILE__, "query_action" :) -> (: call_other, __FILE__, "query_action" :)(原写法在本驱动是表达式函数指针,拿着这些兵器不出招,KB 04 §6.10)。剩下的再跑 scripts/lpc_warnings.py kxkjii2 --fix,共改动 1741 个 .lpc 和若干 .h。 手工:adm/daemons/logind.lpc get_id() 只在 #ifdef MAX_USERS 分支用的局部变量,声明挪进同样的条件里;obj/mailbox.lpc 群发信件 send 时 mail["to", groups[i]]; 什么也没做(LDMud 的多值 mapping 写法),信件没有收信人字段;改成 mail["to"] = groups[i];(kxkj、kxkj1 同改)。 HEAD 与工作树分别加载(新进程):1653 -> 1653 通过,无回退。

启动时警告 91 -> 0;新进程登录正常。

深度功能测试(§10.7,2026-10-08)— .lpc 后缀的定宽切片

.c 改名 .lpc 时只改了字符串没改切片宽度:f[<2..] == ".lpc" 拿两个字符比四个字符,永远不成立(!= 永远成立),按后缀筛文件、去后缀的代码因此从不运行或截成 x.l(KB 06 §7.238)。scripts/lpc_lpc_suffix_slice.py --apply 改了 1 处比较、0 处去后缀(如 adm/daemons/network/httpd.lpc);改动的文件 HEAD 与工作树分别加载(新进程),无回退。

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

深度功能测试(§10.7,2026-10-12):编译警告收尾

可编译文件中的编译警告 62 → 0,不加 pragma。本库与 kxkj 同一份代码:用 lpc_twin_port.py 把 kxkj 同日的修正整体搬过来(57 个文件逐 token 相同,open/start/npc/b_guard.lpc 因 #include 写法不同手改),再跑一轮 toolkit_fix.sh 确认没有本库独有的警告。

发现的真 bug(同 kxkj):

其余(同 kxkj): ITEM + F_LIQUID 容器写出 liquid::long(raw);与 feature/damage.lpc 全局 i/ghost 同名的叶子变量改名(ncount、self_ob),g1.lpc 的 leader 改名 helper;gwhip 的 skill_improved、b_guard 的 greeting 签名;港口房间与 make_room 的原型;冗余继承。

改动的 58 个对象 HEAD 与工作树各载入一次:HEAD PASS 54,tree PASS 57,regress 0,新载入 3(上面 3 个 NPC);open/gblade/npc/wen-fun 两边都因装备不存在的刀在 create() 失败。lpc_audit_removed_locals.py 0 处待看。

独孤九剑招式表越界(2026-10-15,KB 06 §7.243)

同 kxkj:daemon/skill/lonely-sword.lpc 取招越界(8 招按 15 招取),加 pick_action() 收在最后一招。

存档读不出来:BIG5/GBK 0x5C 字后的反斜杠(2026-10-15,KB 03 §4.4)

/data/board back/bss.o、/data/board back/guilty.o、/data/board back/hide_b1.o、/data/board back/skillswy_b.o、/data/board back/sun.o、/data/bss_record/heart.o、/u/w/wade/chinese.o:第二字节为 0x5C 的字(功、许、么、俞、賊……)MudOS 存档时写成 \\,转成 GB 后字保留,多出的一个反斜杠转义了后面的引号(成功\", 字符串收不了尾),或反过来,MudOS 当作被 0x5C 转义的引号成了字符串的结尾(出\"俞" >)。restore_object() 报 Illegal mapping format,留言板等从空白开始。在出错处去掉或补上这一个反斜杠,直到能读回(scripts/lpc_save_encoding.py --from-raw),驱动核对全部能读回。

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

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

去掉的预定义宏 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):adm/daemons/network/netmail.lpc、obj/token.lpc。token 是帮派领袖信物;netmail 是网络邮件守护进程(本库缺 mailer.h 等头文件,改后仍载入不了)。改后用 lpcc 逐个载入这些对象:1 个通过,1 个还有别的错误(adm/daemons/network/netmail:/adm/daemons/network/netmail.lpc:17: error: Cannot #include mailer.h)。

move() 的目标房间文件不存在时不再抛错(2026-10-18,KB 06 §7.96)

feature/move.lpc 的 move() 把 err = catch(dest = load_object(dest)) 当存在检查,可目标文件不存在时 load_object() 返回 0、catch 不触发,接着 dest->receive_object() 抛出 Bad argument 1 to EFUN call_other()。留言板 std/bboard.lpc 的 setup() 把自己 move() 到 location 房间,那是巫师的私人房间时(档案里没有这个文件),留言板连同刷出它的房间一起载入不了。catch 之后补上 if (!objectp(dest)) return 0;(kxkj 系是 ob),移动失败、对象留在原处。抽样(每库 300 个对象)里原先因此失败的 30 个对象,现在 21 个能载入。

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 载入不了,刷出它的房间也少一个人。本库有 1 个对象设了本库没有文件的武功(1 个名字,最多的是 fonxanforce)。三处都改成 return:这一门武功不给、不映射,对象照常载入,只是少了它(缺的武功本身仍是内容缺口)。抽样载入这些对象:1 个里 1 个通过。(scripts/lpc_guard_set_skill.py)

全局头文件丢了 1 个宏(2026-10-19,KB 04 §6.16)

/include/globals.h 里没有定义 MAILDIR,用到它们的物件(名单里 1 个)编译时报 Undefined variable/Undefined function,整个物件载入不了(编译器在第一个未定义的名字上停下,后面的错误和警告都看不到)。同系的库在各自的头文件里都有这几行:照其中和本库共有文件最多的那个库,原样补到 /include/globals.h 最后一个 #define 之后,宏体里出现的路径在本库里都存在。名单里的物件除了这几个宏之外还有别的错误,暂时仍载入不了。(scripts/lpc_restore_defines.py)

BIG5 的 0x5C 尾字节(扩展)(2026-10-19,KB 06 §7.266)

BIG5 里 功 等字的第二个字节正好是 0x5C(反斜杠),作者在它后面多写了一个 \,转 UTF-8 后这个多出来的 \ 跑到了收尾引号前面,把引号转义掉,字符串一直吃到文件后面。scripts/lpc_fix_big5_quote_backslash.py 原先只在引号后面跟 , ) ; } ] + 或行尾时才删;这次把“引号后面紧跟颜色宏再接字符串”(HIY"功\"HIR"』")也算进去,删掉多余的 \。

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 文件。

两个斜杠开头的物件路径(2026-10-19,KB 06 §7.276)

2 个文件、2 处物件路径写成 //…(如 carry_object("//clone/cloth/hic_cloth")):/open/gsword/room1/blood/room1/r1.lpc、/open/gsword/room2/lee.lpc。当年的驱动不介意(路径先被规范化);新驱动把原样的字符串交给 master 的 valid_read(),securityd 按 //clone 查目录,NPC 的 euid 没有权限,报 Read access denied.,NPC 载入不了。改成一个斜杠。

补回本库没有的基类文件,第二轮(2026-10-19,KB 04 §6.15、§6.18)

宏有定义、基类文件却不在档案里:继承它的对象载入时报 Inherited file '…' does not exist!,编译扫描看不到这一类(scripts/lpc_missing_inherits.py 能列出)。同系的库里有同一个文件,原样拷来(scripts/lpc_restore_bases.py);基类和继承它的对象 include 而本库没有的头文件一起带来。每个基类补回后单独载入,再载入使用它的对象,载不进来、或一个用户也载不进来的撤掉了。

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

旧驱动的类型宽松:缺省参数、无类型形参、数组初始化、class 变量(2026-10-19,KB 04 §6.19、§6.20)

原来的 MudOS 把调用少传的参数补 0、把没写类型的形参当 mixed、不检查变量的声明类型与初始值,也允许变量叫 class;这个驱动在编译时全部拒绝,整个物件载入失败。修了 13 个文件:/cmds/arch/edguild.lpc、/obj/dagger.lpc、/open/capital/npc/master_chen.lpc、/open/capital/npcbak/master_chen.lpc、/open/killer/home/rbde.lpc、/open/killer/home/rbds.lpc、/open/killer/home/rbdw.lpc、/open/killer/home/rbe.lpc 等 13 个(scripts/lpc_round_files.py 的修复轮:调用处补写 0、无类型形参补 mixed、string X = ({...}) 补星号、void 函数的返回值,以及 class 变量改名 pick_class)。逐个文件在 HEAD 和改后载入对比:这些文件里 5 个原来载入失败、现在载入,没有退步。

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") && ...):/daemon/skill/moon_sword.lpc(1 处)。

一个巫师目录里的 NPC 多出来的局部变量(2026-10-19,KB 04 §6.10)

u/w/wade/npc/lover.lpc 的 string who, dir, master, item; 四个局部变量都没有用到(这个文件因为前面的修复才开始能载入,终局扫描才看到警告),删掉。

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

daemon/class/blademan/obj/mkblade.lpc:注释写明 sharp 在 8 以上的武器和材质为 blacksteel / crimsonsteel 的刀剑(倚天剑、屠龙刀)不会被血气特攻溶毁,条件却写成 material != "blacksteel" || material != "crimsonsteel"(永远为真),这两把刀照样被毁;改成 &&(两处)。

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,共 2 处)。改动:/daemon/skill/dragon-blade.lpc(1 处)、/daemon/skill/lungshan.lpc(1 处)。

登录密码超过 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)。

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

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

(: 函数 :) 指针指向对象自己没有定义的函数(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。 还剩 4 个函数没有补(other 4):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/daemon/class/killer/obj/ninja-force.lpc:force_damage、/daemon/skill/darkforce.lpc:force_damage、/daemon/skill/ejinforce.lpc:force_damage、/daemon/skill/god-try.lpc:sp_attack2。

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

这个库的 12 个文件里有 25 处 write_file("/log/nosave/...") / log_file("nosave/...")(static 改 nosave 时连字符串里的日志路径一起改了,原来是 log/static/):nosave/CRASHES、nosave/PURGE、nosave/NEW_CRASHES 等。压缩包和站点包里没有这个目录,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 的新进程):补目录前报上面的错误,补后写成功。

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

这个库的代码往 log/ 的 7 个子目录写日志:log/BUG(daemon/class/blademan/master_mou.lpc)、log/RECORD(adm/daemons/channeld.lpc)、log/appo(daemon/class/swordsman/sun_fire_sword/sha_kee.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/BUG、log/RECORD、log/appo、log/mblade、log/net、log/sky、log/sword 记进 scripts/wasm_keep_dirs.txt(scripts/lpc_keep_log_dirs.py;站点和 pristine 树按它建空目录)。证明(scripts/lpcc_eval.py,在 /adm/daemons 这类目录下的求值对象里写 /log/zzdirprobe/...,新进程)见 KB 06 §7.358 的实测表。

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

原档按字节算字符串区间(一个汉字 2 字节):name[2..3] 是名字的第二个字,name[0..1] == "澄" 问名字是不是以「澄」开头。转成 UTF-8 之后,这个驱动的区间和 strlen() 都按字符算(strlen("澄观") 是 2,"澄观"[0..1] 是两个字),老算术原样留着、意思全变:各派掌门的辈分判断(name[0..1] == "澄")永远不成立。

本库 1 处(1 个文件):与汉字常量比较 1 处。例:msg[0..1] != "【" → msg[0..0] != "【"(/feature/message.lpc:45)。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) < 2) || (strlen(name) > 12)) {(/adm/daemons/logind.lpc:1131)。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 区间 1 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。

Gsword 出口仍指向 /u/b/bigcat(2026-10-23,KB 06 §7.371)

剑客区已在 /open/gsword/,出口与 mob 路径仍写 /u/b/bigcat/…。scripts/lpc_fix_bigcat_gsword.py 在目标存在时改写;无对应文件的 ntree/wtree/etree 出口删除。本库 36 处。证明:kxkjii2 的 forest3 HEAD 北向 /u/b/bigcat/room/forest4,改后 /open/gsword/room/forest4 可加载;tree1 只剩南向回 tree。

巫师区出口 faceoff / rence / niulang / yihua(2026-10-23,KB 06 §7.372)

/u/f/faceoff/、/u/r/rence/、/u/onskyer/niulang/、/u/skinys/yihua/ 对应区域已在 /open/world1/faceoff/bird/、/open/prayer/、/d/niulang/、/d/yihua/。scripts/lpc_fix_wizard_area_exits.py 在目标存在时改写,仍缺失的出口行删除。本库 12 处。证明:dreamofseven wood5 四向可加载;xlqy_new2007 天河东西向 niulang;kxkj kitchen7 → prayer。

/open/ 上残留的 == !"…" / || "…"(2026-10-23,KB 06 §7.280 / §7.281 Also)

与 kxkj 同源:deserter.lpc、doorm.lpc 两处(见 §7.280 / §7.281 Also)。/open/ 不再被 SKIP。

小火龙学者/毒师闪避分支恒假(2026-10-23,KB 06 §7.282 Also)

与 kxkj 同源:small-dragon.lpc 一处(§7.282 Also)。

/open/ 上残留的条件赋值(2026-10-23,KB 06 §7.290 Also)

与 kxkj 同源 15 文件(§7.290 Also)。

/open/ 上丢失引号的 shout/say(2026-10-23,KB 03 §4.6 Also)

与 kxkj 同源:open/poison/npc/low.lpc(庄静柔)。见 §4.6 Also。

/open/ 上残留的 score/HP 条 *2(2026-10-23,KB 06 §7.365 Also)

与 kxkj 同源:open/killer/obj/two.lpc(§7.365 Also)。

/open/ 上残留的 force 当 wound(2026-10-23,KB 06 §7.241 Also)

与 kxkj 同源:open/steeple/obj/npc/npc48.lpc(§7.241 Also)。

/open/ 上残留的 .c 路径字面量(2026-10-27,KB 06 §7.356 Also)

lpc_fix_dotc_path.py 曾把 /open/ 当巫师家跳过。open/killer/home/r0u.lpc 的货物表仍写 "/open/killer/npc/train_a.c",档案是 train_a.lpc;显式扩展名按原样解析,new() 得 0。改为 .lpc。证明:lpcc_eval HEAD new(...train_a.c) 为 0,改后 new(...train_a.lpc) 为对象。

open 下死出口由对侧房间修好(2026-10-27,KB 06 §7.257 Also)

lpc_fix_dead_exits 的 SKIP 曾把 /open/ 当巫师目录。本库本批出口改写见该提交(大小写/错名,由对侧出口回指判定)。证明见 KB。

对象路径残留 .c 后缀(2026-10-27,KB 06 §7.356 Also)

set("objects"/"exits", …) 与 __DIR__"….c" 在改名为 .lpc 后仍带 .c 时,new/load_object/房间 reset 找不到文件(血池房 inv=0)。凡旁有对应 .lpc 的,去掉 .c 后缀。证明:HEAD stone2 reset 后 inv=0;改后 inv=1(/d/youxia/obj/blood)。

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