Demon Angel II

✅ 可玩

国家制度的MUD DA

gjzddmudda

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

▶ 开始游玩 · Play Now

一个 ES2 血统的 MUD(作者自己在横幅中致谢 Annihilator/ES2),游戏内标题为"葫芦Ⅱ / Demon Angel"(泥潭中国简化版本)。档案名"国家制度的 MUD"名副其实:`cmds/king/`(封官、收税、传送)与 `cmds/min/`(宣战、结盟、抓捕/放逐、建设、国库)构成一整套玩家可操作的国家经营系统,`buy_kingdom` 甚至能让玩家白手起家、直接购买并建立自己的王国,配备专属王座;大臣还能用 `makeroom`/`linkroom` 一类指令在游戏内直接建造、连接国土场景,在这批档案里是独一无二的治国玩法。新角色从葫芦城中央广场的流浪冒险者开始,城中商铺、公共留言板与专属 NPC 一应俱全;`d/ship/` 一线还提供船只玩法。死亡/复活系统采用单次无条件 `call_out` 送回重生点的简洁结构,不像其它 ES2 血统档案那样存在多阶段判官流程带来的复活软锁风险。

English

An ES2-lineage wuxia MUD (the login banner itself credits “Annihilator/ES2”) whose in-game title is “Gourd II / Demon Angel” (葫芦Ⅱ), a Chinese localization. Its standout feature is a genuine player-run nation-building system unique in this collection: cmds/king/ and cmds/min/ give a king and appointed ministers real commands to declare war, form alliances, arrest/banish subjects, tax, build, and even construct and link new rooms in-world -- buy_kingdom lets a player found their own kingdom outright, complete with a throne room. New characters start as wandering adventurers in the Central Plaza of Gourd City, with working shops, a real bulletin board, and named NPCs; the death/revival cycle is a single unconditional call_out back to the start room, unusually free of the soft-lock class other ES2-lineage libs in this collection suffer from.

README

内容亮点

注册流程

英文名字(3-12 个英文字母)→ 确认建立(y/n)→ 中文名字(1-6 个中 文字)→ 密码(≥5 字元)→ 确认密码 → 电子邮件地址 → 性别(m/f)。

本次修复的关键 bug

没有发现任何需要修改的 mudlib 代码——在 WASM 下开箱即用。这个档案 的 is_chinese()/check_legal_name() 本来就是正确的 Unicode 码点 判断,不像本次处理的其他大部分 ES2 血统档案那样有旧版 GBK 字节假 设的问题。

深度功能测试新发现的 bug(§10.7,2026-08-04)

管理员账号 / Admin account

管理员名单存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常 注册流程创建。这个版本的 logind.lpc 把"目前权限:"+ wizhood() 的 状态显示行注释掉了(死代码),所以游戏画面上看不到明确的权限提 示——但 adm/etc/wizlist 的格式已经对照 securityd.lpc 的解析逻辑 核实过,和本次处理的其他所有 ES2 血统档案完全一致。

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

本地运行

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

游戏端口:40122。

NOTES · 移植与修复记录

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

ES2 血统代码库(作者自己的横幅致谢 Annihilator/ES2),游戏内标题为"葫芦Ⅱ/Demon Angel"("泥潭中国简化版本")。没有发现 mudlib bug——WASM 下开箱即用,全程零修改;is_chinese()/check_legal_name() 本来就是正确的码点判断,和本次会话处理过的大多数 ES2 衍生分支不同。管理员账号(fluffos/Mud@2026)通过真实注册流程 + adm/etc/wizlist 播种(格式已对照 securityd.lpc 的解析器核实,和本次会话处理过的其它 ES2 血统档案一致)——这个分支的 logind.lpc 把"目前权限:"+ wizhood() 状态行显示注释掉当作死代码,所以在对话记录里看不到直接的管理员权限确认,只能从 wizlist 格式正确来推断。

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

此前只验证到注册流程本身,本轮原生 driver(端口 40122)走完了移动、 留言板、商店、战斗的完整会话,并且用真实读代码的方式核实了死亡/复活 系统不属于本项目已归档的 §7.68 类别。

主动检查(对照 AGENTS.md 已归档的 bug 类),发现并修复两个真实 bug:

确认不是 bug 的检查项:

完整游玩记录: 1. 用真实中文名"沈牧"(id shenmu)注册成功,落地"中央广场"(葫芦 城),场景里有真正可读的留言板("留言板(Board)")和 NPC"小美 女"。 2. 移动:中央广场→西大街→西大街(内部两间不同描述的分段房间)→ 西城门(死路,唯一出口 east)→中央广场→南大街→中央广场→北大 街(recall_n_1)→北大街(recall_n_2,出现真正的商人 NPC)。 沿途确认这批"XX大街"房间是多段拼接的独立房间文件(不同段描述文 字不同),不是同一个房间的重复输出。 3. 留言板测试:read 1 成功读出一条真实的、带分页器的长留言(标 题"给拿到本 MudLib 的人",作者 bor),分页器的 ENTER/q/b 翻页逻辑正常。 4. 商店测试:北大街的商人(d/gourd/npc/mob1.lpc,inherit MISC_SHOP_NPC)list 正确显示"马豆"和"普通药水"两样商品及库 存;buy bean(注意命令格式是 buy <物品名>,不需要 from <商人>)在零金币情况下被正确拒绝("你的钱不够。")。 5. 战斗测试:kill man(商人)触发正常的回合制拳脚对轰,双方都是 1 级新手(con 相同、无武器),大量交换但双方命中率/伤害都极 低(score 显示"最小伤害力 1"),这是新手无武器徒手数值偏低的 内容/数值现象——本次测试没有让任一方在合理时间内真正死亡,改用 代码走读的方式确认了死亡系统本身的实现(见上方)。整场战斗 debug.log 全程没有任何错误。 6. 未能找到"国家制度"玩法(cmds/king//cmds/min/)的可达入口—— 新手初始身份是"冒险者",购买/继承国家需要走 d/gourd/buy_kingdom.lpc 等专属流程,本轮测试预算内没有深入这 一部分,留给后续更长的会话。

结果:整个测试会话(含一次修复后重启验证)debug.log 全程为 空,没有任何真实的 error:/Bad argument/No program/Too deep recursion 记录。测试角色存档(data/{login,user}/s/)保持未跟 踪;测试期间因为 driver 常驻产生的国家系统共享存档 open/sky/kingdom_data.o 的周期性 churn 已在提交前还原,未计入本 次改动。两处代码改动已用 formatter 校验({"errors":0})。

第四轮深度测试(round-four,2026-08-20)

本轮专门补齐第一轮明确留白的两项:国家制度(cmds/king//cmds/min/) 和真实战斗死亡,并顺手对标准 bug 清单做了一次全新(非复查)扫描。

测试帐号:fluffos/Mud@2026 此前只在 adm/etc/wizlist 里被 "播种"过,本轮开局才发现 data/{login,user}/f/fluffos.o 从未真正存 在——第一轮 meta.json 里"管理员账号通过真实注册流程...播种"的说法 其实是推断,不是已完成的动作。本轮走了一次真实注册流程创建了它, score 确认 wizlist 授权生效(goto/call 等巫师指令可用)。这 个帐号按本项目惯例保留(帐号存档已 git add),不是一次性测试角色。

国家制度(buy_kingdom / cmds/king / cmds/min)

真实战斗死亡

§7.100 全新命中并修复(本档案此前从未被扫描过,低于 100 次的语料库扫描门槛)

grep -c "replace_program(ROOM)" 只有 49 次(其它宏如 HERB_SHOP/ GATE/TAVERN/SMITH 等还有更多),远低于当时 corpus 扫描用的 100 次门槛,因此完全没被那 166 库的批量扫描覆盖到,是本轮第一次真 正检查。确认全部 87 处都是"inherit X; 后又在 create() 里多余 自我 replace_program(X);"的标准 §7.86/§7.100 形状(含 obj/board/wizard_j.lpc 这个真正的留言板实例,和 §7.86 原始症状 完全一致:inherit "/std/jboard" 后又 replace_program("/std/jboard"), 而 jboard.lpc 的 post/回帖流程恰好用闭包 (: done_describe_project, ... :) 绑定 input_to,是典型的"迟早会撞上闭包绑定就崩"的地雷)。

用二进制安全的脚本按"每文件对应的 inherit 目标"精确删除了 87 处独 立房间/建筑档案里的多余调用,另外手工修掉了 4 处把同样毒瘤写进"造 房子"生成模板字符串里的工厂档案(这样以后用这些工具新建的房间不 会带着地雷出生):

共 91 个文件、96 处出现全部清理(另有 2 处 d/gourd/choice_class.lpc 和 d/gourd/recall_shop.lpc 里的调用本来就已经被 // 注掉,原样 保留未动)。修复后现场用 min makeroom/min build 亲自建了两间房 (其中一间成功、一间被房间数门槛正常拒绝),走进新建房间验证正常 加载、debug.log 没有出现 §7.100 特征的"cannot replace a program" 告警。

顺手修复:cmds/min/build.lpc 里 3 处原始档案自带的反斜杠损坏

和第一轮 adm/daemons/chard.lpc 那处"一具枯\干的骸骨"同一类损坏 (编译期直接触发 Warning: Unknown escape sequence,本轮修 §7.100 时在这个文件里现场读到的):训练厅描述"有许\多人"、马厩描述"马厩\ ,"和"马厩\被"三处游离反斜杠,已按上下文改回正常标点("有许多人"、 "马厩,"、"马厩被")。语料库里还有其它 8 个档案有同样"许\多"/"厩\" 字样(combatd.lpc、feature/liquid.lpc 等),但本轮只修了实际测 试路径上现场读到警告的这一处,其余留给未来专门扫描,不在本轮范围 内主动展开。

标准 bug 清单全新排查结果(本档案此前未被任何一次语料库扫描覆盖)

清理

open/shice/(测试国家的房间、kingdom_data.o 等)、 data/{kingdom,nuke/kingdom}/shice/ 全部删除;测试账号 fluffos 的 kingdom/home/cwd 属性已清空并显式 save(),hp/mp 重设为满值 并 save()(战斗死亡测试用 call 把 hp 打成负值后,die() 虽然 在内存里正确把 hp 复原到 30 并持续自然回血,但期间没有任何一次显 式 ->save(),driver 关闭前的最后一次磁盘落地反而是负值——这是测 试方法本身的副作用,不是死亡/复活系统的 bug,已经手工修正并确认 后续重连不再触发误报死亡);测试遗留的尸体对象已用 dest 清除; git checkout 还原了测试期间因 driver 常驻产生的两处共享存档周期 性 churn(data/chinese.o、open/sky/kingdom_data.o,后者的字段 重排序/sky 王国自身经济模拟数值漂移,和第一轮记录的同一份文件同 一种 churn)。

结果:本轮修复的所有文件均在真实 build-debug driver 上验证 过干净编译和干净启动(debug.log 全程无编译警告之外的 error:), 国家制度和真实战斗死亡两条主线均现场跑通。

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

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

§10.7 deep functional test, round three (2026-09-01): genuine two-account multiplayer nation testing

This pass deliberately covered the angles the two prior passes explicitly left untested: a SECOND real player account interacting with the king account inside the nation system (appoint/teleport/fire), currency persistence across a real quit+reconnect, adversarial/malformed kingdom-system input, and a real board post. Standing admin account fluffos/Mud@2026 played the king; a brand-new throwaway account xiaolong/王小龙 (deleted afterward, not committed) played the citizen/minister. Native driver on port 40122, driven via a two-socket Python script (not committed, scratch-only), debug.log checked after every state-changing command.

Two real bugs found and fixed, both verified live:

Confirmed clean / no bug found, despite active testing:

Cleanup: driver restarted once mid-session to pick up the #include-based simul_efun fix (§10.9-documented debug.log-goes-dead convention followed: log inspected via work/log/debug.log after every state change, both before and after the restart). Test kingdom ceshitwo (work/open/ceshitwo/, work/data/{kingdom,nuke/kingdom}/ ceshitwo/) and both throwaway accounts (xiaolong, and a third validation-only account ceshimin that never actually founded anything) deleted, not committed. fluffos's kingdom/home/cwd/ cwf properties cleared and hp/mp reset to full via explicit set() + save() (a testing mistake along the way — first attempt used a wizard call me->set("hp", me->query("base_hp")), which the call command's own simplistic argument parser treats as a literal string, not a nested expression, corrupting hp/mp into a broken string that then crashed heart_beat()'s >= comparison every tick; caught via the very same debug.log-after-every-command discipline this methodology requires, and fixed immediately with plain integer literals instead — recorded here as a reminder that this driver's wizard call command does not evaluate nested -> calls in its arguments). Ambient save-churn from this session (data/chinese.o's kingdom-name lookup dict gaining a stale ceshitwo entry, open/sky/kingdom_data.o's known pre-existing periodic economic-simulation drift, login-timestamp noise) reverted via git checkout before committing; only the two real .lpc fixes plus fluffos's own cleaned-up save file are included in the commit. A final fresh driver boot + login/score/look/ quit cycle confirmed a clean debug.log throughout.

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

scripts/lpc_fix_negative_ranges.py: 6 line(s) in 3 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)— tail() simul_efun

scripts/lpc_add_tail.py --apply: cmds/wiz/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)— 编译警告整理

scripts/lpc_warnings.py gjzddmudda --fix 加 scripts/lpc_fix_no_effect.py --apply,共改动 154 个 .lpc。HEAD 与工作树分别加载(新进程):142 -> 142 通过,无回退。

启动时警告 34 -> 0;新进程登录(新人物确认)正常。

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

scripts/lpc_twin_port.py adopt demonangel gjzddmudda 搬来 demonangel 同日整理(8f6d5cc3823)的改动,与本库逐 token 相同,能编译的文件警告清零;改动的对象在 HEAD 与工作树各载入一次,regress 0。

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

cmds/min/develop 里 "马厩\",(2026-10-18,KB 03 §4.6)

"stable" : "马厩\", 的收尾引号前多了一个反斜杠,把引号转义掉了,字符串连到下一行,命令载入不了。去掉反斜杠。载入:通过。

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

找不到父类函数的 ::fn() 调用(2026-10-19,KB 06 §7.259)

/adm/daemons/virtual/template/room.lpc共 1 个物件里写着 ::create();、::init(); 这类调用,而它们继承的基类并没有这个函数。老驱动把这种调用当成什么都不做、返回 0 的空调用,本驱动在编译时报 Unable to find the inherited function 'init'.,整个物件载入不了。这些物件的错误只有这一种(其他错误清掉之后才露出来的),逐个删掉这些调用(return ::fn(...) 改成 return 0;)。(scripts/lpc_fix_dangling_super.py)

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

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,共 1 处)。改动:/adm/daemons/fingerd.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)。

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。

翻页器 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) ||)。改动:/std/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 个存档共 28 处按 scripts/lpc_fix_save_dotc.py 改成 .lpc(只改 .lpc 存在而 .c 不存在的字符串;玩家存档、备份、留言板、巫师目录和文件索引缓存不动)。改动:/open/sky/kingdom_data.o(24 处)、/open/test/kingdom_data.o(4 处)(共 2 个存档)。

巫师命令不带参数时对 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/wiz/test.lpc(present)。加载检查 HEAD 与工作树对照,没有退步。

长度检查按字节写,旁边的提示按汉字写:8 处(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 你好吗)。本库 8 处(4 个文件):if ((strlen(name) < 2) || (strlen(name) > 12)) {(/adm/daemons/logind.lpc:448);if ((strlen(name) < 4) || (strlen(name) > 12)) {(/cmds/usr/chfn.lpc:39)。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 区间 6 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。

blue_cloth F_CLOTH → BODY(2026-10-27,KB 04 §6.25 Also)

d/obj/npc/wp/blue_cloth 写 inherit F_CLOTH,本库无该宏。改为本库的 inherit BODY,护甲 2 写入 armor_prop/armor。证明:HEAD 失败;改后加载成功。

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

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