info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
一个以古龙小说为背景的"风云"MUD。这份档案的实际游戏地图相当单薄:全库只有约 48 个带房间描述的文件,且大多数分散在各个巫师的个人目录下,而不是一套完整的官方城镇/门派地图;唯一较为完整的官方场景是 `quest/kaifeng/` 的开封"衙门",包拯、展昭都驻扎在此。注册流程把管理密码与登录密码彻底分离,比常见的单密码注册更谨慎。
English
A Gu Long-themed “Storm” (风云) MUD whose actual built world is thin: only about 48 files carry real room descriptions, most scattered across individual wizards' personal directories rather than a complete official town/sect map. The one substantially finished official area is the Kaifeng yamen (衙门) scene, populated by Judge Bao (包拯) and Zhanzhao (展昭). Registration uniquely splits a recovery/admin password from the everyday login password. The apprenticeship/sect system itself works, but no NPC in the shipped content ever actually sets a sect to join.
README
内容亮点
- 这份档案的实际游戏地图非常单薄:全库只有约 48 个带房间描述的文 件,且大多数分散在各个巫师的个人目录(
u/)下面,而不是一套完 整的官方城镇/门派地图——比较接近一个仍在搭建中的骨架,quest/ kaifeng/的"衙门"(zhengtang) 场景是少数看起来完整的官方内容。 - 管理密码与登录密码彻底分离(详见下方注册流程),比常见的单密码 注册更谨慎。
- 本次修复过程中发现并记录进 AGENTS.md 的一个新 bug 类别(§7.60):
master.lpc的log_error()在CHANNEL_D完成加载之前广播编 译警告,会触发驱动禁止的嵌套编译,把一条无害的 pragma 警告刷成 几万行重复错误堆栈——这个发现后来在本轮好几份档案(xyj20032等)里都复用了同样的修法。
注册流程(两套密码)
英文名字 → 确认建立(y/n)→ 中文名字(2-4 个中文字)→ 管理密码 (≥5 字元,用于遗失普通密码时找回、修改密码,平时不要用)→ 确认管 理密码 → 普通密码(≥5 字元,日常登录用,不能和管理密码一样) → 确认密码 → 民族(0-3)→ 性别(m/f)。
本次修复的关键 bug
- 新发现,已收录进 AGENTS.md §7.60:
master.lpc的log_error()——每一条普通的编译警告(不只是真正的错误)都会调用它——最后会执 行CHANNEL_D->do_channel(...)。如果CHANNEL_D这时候还没有被 preload(取决于它在adm/etc/preload里排在第几个),这次调用会 在调用者自己还在编译的过程中,悄悄触发对channeld.lpc的一次新 编译——这个驱动禁止这种嵌套编译,于是抛出*Object cannot be loaded during compilation.,又被log_error()自己捕获并重新记录一次,如此循环,把一条本来毫无意义的 pragma 警 告变成了几万行重复的错误堆栈输出。这个问题只存在于CHANNEL_D加 载完成之前的极短启动窗口内(之后完全正常),但足以把真实输出淹没 到没法看,因此还是修了:在广播前先判断find_object(CHANNEL_D)。 is_chinese()和check_legal_name()都沿用旧版 GBK 字节双字节 假设(字节区间判断 + 长度界限按字节数而非字符数 + 逐字节跳步循 环),导致所有真实中文名字(包括标准测试名字)都被拒绝。已按 AGENTS.md §8.1 的标准做法修复。
管理员账号 / Admin account
- id:
fluffos - 密码 / password:
Mud@2026 - 权限 / level:
(admin)
管理员名单存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常
注册流程创建(管理密码另设为 AdminPw1,与登录密码不同)。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。
本地运行
cd libs/fyzfqyy
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40133。
NOTES · 移植与修复记录
WASM 修复摘要(迁移自 meta.json 的 group_note)
风云(古龙小说题材),管理密码+登录密码双密码注册流程。新发现的 bug,已收录进 AGENTS.md §7.60:master.lpc 的 log_error()——每一条普通的编译警告(不只是真正的错误)都会调用它——最后会呼叫 CHANNEL_D->do_channel(...);如果 CHANNEL_D 这时候还没有被预载(取决于它在 adm/etc/preload 里排第几个),这次呼叫会在调用者自己还在编译的过程中,悄悄触发对 channeld.lpc 的一次新编译——这个驱动禁止这种嵌套编译,于是抛出"*Object cannot be loaded during compilation.",又被 log_error() 自己捕获并重新记录一次,如此循环,把一条本来毫无意义的 pragma 警告变成了几万行重复的错误堆栈输出。这个问题只存在于 CHANNEL_D 加载完成之前的启动窗口内(之后完全正常),但足以把真实输出淹没到没法看,因此还是修了:在广播前先判断 find_object(CHANNEL_D)。另外也修复了 is_chinese() 和 check_legal_name() 里经典的 §8.1 中文名字 bug(长度界限+字节步进循环,会静默拒绝所有真实中文名字)。排版格式化工具的第三类盲点检查在 12 个命中里抓到了两处真正的损坏(一份巫师培训测验文字档案和一份带有未转义尾随中文注释的代码速查表)——两处都已还原。管理员账号(fluffos/Mud@2026)通过真实注册流程 + adm/etc/wizlist 播种。
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 13 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
深度功能测试 / Deep functional test (AGENTS.md §10.7)
管理员账号 fluffos/Mud@2026(管理密码 AdminPw1,与上面 WASM 摘要记录的
一致)在本仓库当前 checkout 里其实没有实际的存档数据(只有
data/{login,user}/{a-z}/ 的空骨架目录被播种进 git,账号本身的 .o 存档
从未提交)——先用 ls data/login/f data/user/f 验证过,确认为空后,本轮
按 README 记录的凭证通过真实注册流程重新建立了一次(英文 id 沿用
fluffos,登录密码沿用 Mud@2026,管理密码沿用 AdminPw1)。
新手引导先读了 doc/help/newbie.txt:文档描述的注册流程(单一密码→确认→
email→性别→民族)已经过时,与当前 logind.lpc 实际代码不符——真实流程
是 README 记录的双密码版本(英文名→确认→中文名→管理密码→确认→普通密码→
确认→民族→性别,注册时不问 email)。doc/help/newbie.txt 关于
apprentice/skills/learn/战斗系统的说明与代码基本一致,仅密码段落已
过时,未改动帮助文档本身(内容维护,不在本轮范围)。
用真实中文名字 云舒(英文 id ceshiwo)走完整个注册流程:look/
score/i 在角色创建后、register <email>+decide(風雲用开封府门口的
神仙姐姐 NPC 做真人自助注册,不是 cmds/arch/register.lpc——那个指令需要
(arch) 权限,是给巫师手动帮别人登记用的,一般新玩家永远碰不到,房间牌子
上写的 register your-email 指的是神仙姐姐身上的本地 register/decide
动作)自助完成注册后,均正确响应、无崩溃。
战斗安全陪练机制:cmds/std/fight.lpc 读到确认,判断依据是
obj->query("can_speak")(不是 civilized)——adm/daemons/race/human.lpc
的 create() 无条件把人类设成 can_speak=1,beast.lpc/monster.lpc
两个种族档案都没有设这个属性,因此人形 NPC 走 fight_ob()/fight_ob()
双向切磋分支,兽类/妖魔走 kill_ob() 真杀分支——与本项目本轮反复确认的
"can_speak/civilized 二选一分流"模式一致,本档案用的是 can_speak。现场
用管理员账号对 quest/kaifeng/npc/zhanzhao.lpc(展昭,人类,can_speak=1)
分别测试了 fight(见下方"发现但判定为既有设计"关于死亡的记录)和真实的
可用 NPC 人数极少这一事实本身(见下)。
组织/门派技能获取:organic 与管理员捷径都验证了,但都撞上同一个内容缺口
- organic 路径(
apprentice):cmds/skill/apprentice.lpc本身逻辑完 整(ob->query("family")判断对方是否已开山立派、family/privs==-1 判断是否掌门),但全档案(u/巫师个人目录除外)没有任何一个 NPC 设置了"family"属性——grep '"family"'全档案命中的都是读取/展示family的 命令文件,没有任何 NPC 的create()真正set("family", ...)。也就是说 官方内容里没有一个可以拜师的门派掌门,apprentice指令本身可用,但找不 到合法目标——与 README 已经记录的"地图是骨架"是同一类内容缺口的延伸(不 只是地图,门派体系本身在官方内容里也从未搭建),未改动代码。 - 管理员捷径:
cmds/adm/setskill.lpc((admin)权限)存在,可以直接ob->set_skill(skill, level)/ob->delete_skill(skill),但没有任何单独 的"授予门派"指令(grep -rl '"family"' cmds/adm cmds/wiz cmds/arch零命 中)。如实记录:技能有捷径,门派没有。
修复的程序性 bug
- **AGENTS.md §7.12 的又一个确认实例:
adm/simul_efun/message.lpc的message()模拟函式对第 4 个参数(exclude)零校验直接转发给efun::message(),而这份驱动的message()efun 要求第 4 参数必须是object/array,传int 0会抛*Bad argument 4 to EFUN message():全档案有几十处调用点(message ("system", str, me)、message("vision", ..., obj)、adm/daemons/channeld.lpc:474的频道广播等)沿用旧驱动"缺省参数静默补 0"的写法只传 3 个参数,这份message()本身没有varargs,缺的参 数按这份驱动的行为会被填成int 0,然后原样转发给efun::message()炸掉。爆炸半径极大且会自我循环:任何一次编译警告触发master.lpc的log_error()→CHANNEL_D->do_channel()→这个message(),报错本身又被当成新的一条编译期错误重新走一遍同样的路径, 冷启动单次干净重启就能刷出 1500+ 行重复堆栈(比 §7.60 已经修过的嵌套编 译问题更隐蔽,因为 §7.60 的 guard 已经生效但这个是一个完全独立的第二个 循环源);玩家侧最直接的后果是每一次重新登录都会在enter_world()的tell_room()广播处崩溃**(obj/user#N的move()→tell_room(startroom, ..., ({user}))→message()),并被logind.lpc:check_ok()的外层catch()拦下显示"你无法进入这个世界, 可能你的档案出了一些问题"——每个已注册玩家的每一次重新登录都会看到这条 吓人的错误。修复:在message()里补一道类型校验,exclude不是object/array就强制改成({})再转发。现场复测:冷启动干净(0 处Bad argument 4),重新登录不再触发这条错误路径。 - AGENTS.md §7.25 的又一个确认实例:
std/room/room.lpc的make_inventory()对new(file)的返回值零校验:new()对一个不 存在/已搬迁的路径静默返回0(不抛错),随后ob->set(...)/ob->move(...)对0呼叫call_other直接抛*Bad argument 1 to EFUN call_other(),而且这个未捕获的错误会从reset()的物件生成迴圈里一路往外抛,导致同一个房间"objects"清单里 排在它后面的其它 NPC/物品全部被跳过、整个房间一次 reset() 全部作废 (现场用quest/kaifeng/zhengtang.lpc复现:清单第二项yayi路径写 错——见下——导致清单第一项bao(包拯)也从未真正摆进房间,look只 看到空房间)。修复两处:①make_inventory()本身对new()返回0的情况直接跳过(不再对空物件呼叫方法);②reset()迴圈里两处make_inventory()调用都补上catch(),让单个坏条目不再连累同一次 reset() 里其它条目的生成。现场复测:quest/kaifeng/zhengtang.lpcreset 后look正确显示包拯,即使清单里第二项yayi因为下面记录的 另一处独立内容缺口仍然创建失败,也不再拖累包拯。 adm/simul_efun/object.lpc的unew()对new(str)返回值零校验: 和上一条同一种形状,ob = new(str)之后立刻ob->query("unique"),str指向不存在的档案时ob是0,直接抛*Bad argument 1 to EFUN call_other()。unew()是carry_object()(几乎每一个 NPC 的create()用来穿装备)的底层实现,任何 NPC 的任意一件"应该存在但其实 不存在"的装备档案都会让该 NPC 的create()整个中断(后面的技能/ 金钱/inquiry 设定全部不执行)。修复:ob为0时直接原样回传,不再 继续query。quest/kaifeng/zhengtang.lpc的"objects"清单里yayi的路径写 死成/d/fy/npc/yayi(本档案从未出货的d/fy地图树下),但真正的yayi.lpc其实就在同一个quest/kaifeng/npc/目录下(挨着清单第一项bao用的__DIR__ "npc/bao"):明显是复制/搬迁时漏改的路径错字, 已改成__DIR__ "npc/yayi"(与清单里bao那一项写法保持一致)。改完 后yayi能正确装载,但其create()自己又装备了两件/d/fy/npc/ obj/下的兵器/护具(这部分才是真正的内容缺口,见下方"既有设计"一节, 未改动)。quest/kaifeng/npc/zhanzhao.lpc的carry_object("/obj/cloth"): 路径缺了档名,应该是/obj/cloth/cloth(全档案其它每一处需要给 NPC 穿基础布衣的地方——obj/npc/garrison.lpc、bing.lpc、bingtou.lpc、danei.lpc、logind.lpc的新角色初始化——全部用的是/obj/cloth/ cloth,只有这一处写漏了)。/obj/cloth本身是目录不是物件档案,new("/obj/cloth")返回0,接上面unew()修复后不再崩溃,但穿戴 会静默失败;已改成正确路径/obj/cloth/cloth。- **
feature/skill.lpc的set_skill()/map_skill()/improve_skill()/decrease_skill()/research_skill()五处error("F_SKILL: No such skill (...)")——本档案(u/巫师个人目录除外)从未出货/daemon/ skill/目录下的任何技能档案(unarmed/dodge/parry/force/literate/... 全部缺失,已用ls /daemon/skill(管理员实测"没有这个 目录")和find -iname unarmed*等交叉确认过不是 AGENTS.md §7.5 那种 ACL false-negative,是货真价实的内容缺口)。技能档案缺失本身不在本轮 修复范围(补上 100+ 个技能档案属于游戏内容创作),但error()直接 中断调用者整个函式这件事本身是可以修的:set_skill()抛出时会让呼叫 它的 NPCcreate()从那一行整个中断,后面所有还没执行到的技能/装备/setup()/金钱/inquiry全部不会执行(现场复现:quest/kaifeng/npc/ bao.lpc的set_skill("dodge", ...)是create()里第一条技能呼叫, 炸了以后包拯连衣服/钱/任务对话都没有);如果这次 reset() 又是从make_inventory()里发生的,还会连累同一房间后续物品(即上面已修的 第二条 bug)。五处全部改成:目标技能不存在时写一条日志 (/log/nosave/missing_skill)然后直接跳过这一项,不再中断调用者。 现场复测:bao/yayi/zhanzhao全部能正常摆出装备、setskill管理员指令能正常执行完(虽然因为技能档案本身缺失,实际不会真的写入skills映射——如实告知管理员这一点在指令输出里不会体现,setskill自己的 "setting-> ..." 提示不检查返回值,永远显示"成功",这是既有的 UI 诚实度问题,未改动)。 - 新收录进 AGENTS.md §7.96:
adm/daemons/logind.lpc:enter_world()依赖catch(load_object(...))判断房间是否存在,但这份驱动的load_object()对不存在的档案不抛错、只是静默返回0,导致这段"起始 房间不存在就退回 START_ROOM"的容错逻辑 从来没真正生效过:START_ROOM(/d/fy/church)本身就是本档案从未 出货的地图(同一个已知内容缺口),玩家自助注册(decide)后startroom被设成这个不存在的常量,下一次登录catch(load_object (startroom))因为不抛错而误判"成功",接着user->move(startroom)对不存在的房间呼叫call_other,未捕获,被check_ok()外层catch()拦下显示"你无法进入这个世界"——每一个完成过自助注册的玩家, 之后每一次登录都会看到这条错误,本质是上面message()bug 修好之 后暴露出的下一层问题(两者会先后触发,message()没修之前这条甚至看 不清)。改用file_size(startroom + ".lpc") < 0直接判断是否存在(不 再依赖load_object()的抛错语义),如果连START_ROOM自己也不存在 则再退一步落地到REGISTER_ROOM(/adm/etc/register,本档案确实出货 了)。现场复测:ceshiwo/fluffos两个已注册角色重新登录都不再报错, 正确落地世外桃源。 feature/damage.lpc:die()同一形状:死亡后move(DEATH_ROOM)(/d/death/gate,同样是从未出货的地图)未捕获,导致死后的幽灵化 状态(ghost=1、gin/kee/sen清零、save())已经落盘,但角色 卡在死亡时所在的房间、且DEATH_ROOM->start_death()的复活流程初始化 完全没跑到。现场用管理员角色故意输给展昭复现(见下方陪练分流的死亡记 录),确认崩溃点。修复:file_size判断DEATH_ROOM/DEATH_ROOM_NO_PEN是否存在,不存在则退回REGISTER_ROOM。现场复测:死亡后正确移动到 世外桃源(不再崩溃卡死在原地),复活/幽灵状态其余逻辑未改动。adm/daemons/channeld.lpc:do_channel()假设呼叫者me一定是有name()的角色物件,但adm/daemons/combatd.lpc:victim_penalty()用this_object()(也就是 combatd 这个 daemon 自己)当发言者广播死亡 谣言:daemon 没有name(),call_other静默返回0(不是字串),who = 0之后who == me->name(1)(同样是0)判断为真,进入who += ...分支时因为who是数字类型直接抛*Left hand side of += is a number,导致这条死亡广播(连带victim_penalty()后续所有death penalty 逻辑)在heart_beat()里未捕获地中断。现场复现:管理员角色 被展昭打死后触发。修复:who取到非字串时退回通用的 "系统" 标签,不 再让who += ...对数字做字串拼接。现场复测:死亡广播和后续 penalty 逻辑正常跑完,不再报错。adm/daemons/logind.lpc::get_name()里一处遗留的printf("%O\n", ob)(AGENTS.md §7.34 常见形状的又一实例):中文名字确认成功后立刻 把整个 login 物件的原始表示(/obj/user/login#0 ("0(ceshiwo)")这种) 直接印给正在注册的新玩家看。已删除,不影响后续逻辑。config.fluffos的maximum evaluation cost : 700000(AGENTS.md §7.90 项目模板默认值):冷启动首次因编译警告堆栈过深时命中Eval interrupted: ... cost limit reached, limit: 700000 usec, 已提到5000000(本项目 30+ 个库的常用值)。adm/simul_efun/file.lpc:log_file()缺assure_file()导向导致/log/目录不存在时崩溃(AGENTS.md §7.11 标准形状):新checkout没 有预先mkdir出log/目录时,master.lpc:log_error()里efun::write_file(home + "log", message)直接抛*Wrong permissions for opening file /log/log for append. "No such file or directory", 同一份log_error()里紧接着的CHANNEL_D->do_channel()广播(在 §7.60 已修的 guard 保护下不会再嵌套编译,但仍然会把这条错误继续往外 传递)。修复:log_file()简单模拟函式补assure_file()导向;master.lpc:log_error()自己直接呼叫efun::write_file()(绕过 simul_efun),单独补一次assure_file()。现场复测:冷启动 0 处Wrong permissions。
发现但判定为既有设计、未改动的现象
- 地图/装备/门派/技能内容大面积缺失,是同一份"骨架存档"问题的不同表 现:官方"/d/fy"地图树整体不存在(README 已记录);
/d/wiz(巫师新 闻板挂载点)、/d/death(死亡/复活房间)同样不存在;/daemon/skill/下没有任何技能档案;官方 NPC 里没有一个设置了"family"门派归属。这 些全部是内容缺口,不是程序逻辑缺陷,本轮只修复了"缺失内容不应该让呼叫 者整个崩溃/中断"这一层健壮性问题(见上),没有也不打算补全任何实际的 房间/装备/技能/门派内容。 fight("安全"陪练)在极端实力差距下仍然可能一击致死,与帮助文档 "点到为止,不会真的受伤"的承诺不完全一致:adm/daemons/combatd.lpc对victim->receive_damage("kee", damage, me)的呼叫在fight/kill两种模式下完全一样(唯一的区别是kill模式会额外叠加receive_wound()造成的永久创伤),而std/char/char.lpc:heart_beat()的死亡判定里,kee(不需要真的伤到eff_kee)单独跌破-10 * dur就会直接死亡,不会先进入"昏迷"缓冲状态。现场用一个全新零基础的管理员 角色(对空手战力接近 0)对quest/kaifeng/npc/zhanzhao.lpc(combat_ exp1200万,装备夺命剑)连续测试两次,两次都是单招直接从满血打到 "你死了",全程没有经过"你想要逃跑"式的昏迷/求饶缓冲。鉴于:①这属于战 斗数值平衡/伤害公式的设计范畴,不是崩溃/静默失败/逻辑颠倒;②不清楚原 作者是否本来就设计成"实力差距过大的陪练仍有一击猝死风险"(帮助文档没 有明确排除这种情况,只是没提到);③修改伤害封顶/血量下限属于会改变战 斗数值体验的设计决策——未改动代码,如实记录在此,供后续如果要专门核实 伤害公式时参考。- 管理员/普通玩家的角色重连都会先落回世外桃源:
quit/断线重连都没 有恢复"上次所在房间"的逻辑(enter_world()本身就是按registered/startroom状态重新计算落地点,不是靠断线前记忆位置); 已注册但startroom指向不存在地图的角色会被上面已修的容错逻辑统一送 回世外桃源。神仙姐姐的greeting()对非巫师角色只要出现在世外桃源就 会直接丢进空洞(VOID_OB)——这是这份代码自己的既有设计("已经注册的 普通玩家不该待在这个欢迎房间"),不是本轮改动引入的。 register(cmds/arch/register.lpc)只有(arch)权限能用,与房 间牌子上呼吁新玩家"register your-email"的字面指令名字撞车:实测确 认新玩家真正走的是神仙姐姐 NPC 本地挂载的register/decide两个 动作(add_action),不是这个巫师专用的全局指令;两者恰好同名但是完 全独立的两套实现,不冲突(driver 优先解析房间/NPC 的本地add_action, 全局cmds/arch/指令要显式(arch)权限才会被列入候选,新玩家权限 下SECURITY_D->valid_grant(me, "(arch)")恒为假,指令直接不可见)。 如实记录,未改动,帮助文字/牌子描述与实际机制一致(只是描述得不够精确, 容易让人误以为是同一个指令)。
未验证事项
- WASM:driver 编译工具链需要访问
storage.googleapis.com(被代理拒 绝),本轮未验证 WASM 下的行为,只在原生 driver 上完成全部测试。 - 门派/技能内容缺口意味着"角色成长"这条主线(学武功、拜师、参数点分配到 实战技能上)在当前存档状态下事实上不可玩;已在上面如实记录,供后续如 果要专门"填内容"时参考起点。
Deep functional test round two (2026-08-14)
Independently re-verified against current code rather than trusting the
extensive round-one writeup above. All 10+ round-one fixes confirmed
still present (code inspection for all, live re-exercise of the
highest-value ones — the §7.12 message() type check and the §7.96
START_ROOM fallback, both exercised on literally the first login).
Found and fixed one small remaining gap this round's own checklist
covers that round one's pass didn't touch.
New fix: adm/simul_efun/file.lpc's cat() still had no null-guard
Round one already fixed log_file()'s assure_file() gap (§7.11) but
missed cat()'s separate null-guard need. One-line fix:
write(read_file(file) || "");.
Re-verified live: the two highest-value round-one fixes
- §7.12
message()4th-arg type check: first admin login this pass completed with zeroBad argument 4errors (the original bug made EVERY login crash atenter_world()'stell_room()broadcast). - §7.96
START_ROOM-doesn't-exist fallback: landed cleanly at世外桃源/REGISTER_ROOMon login, exactly the fallback the fix produces (START_ROOMgenuinely doesn't exist in this archive, a documented content gap, not something to fabricate). - §7.25
make_inventory()isolation fix:goto /quest/kaifeng/zhengtang(admin teleport, since/d/fydoesn't exist for organic navigation) reproducedyayi.lpc's owncreate()still throwing repeatedly (*Bad argument 1 to EFUN call_other()) — this is the ALREADY-DOCUMENTED, deliberately-unfixed content gap (yayi's own equipment references/d/fy/npc/obj/..., which doesn't exist). Critically, despite yayi's own failure, the room and 包拯/Bao daren both loaded and displayed correctly — confirming the isolation fix (one broken NPC doesn't take down the room or its siblings) still holds exactly as designed. - Other fixes (
unew()guard, theyayipath fix itself, thezhanzhaocloth-path fix, the 5feature/skill.lpcerror→log-and-skip sites,channeld.lpc's non-string-speaker guard, the printf leak removal, the §7.90 eval-cost bump): all code-confirmed present via direct grep, not independently re-triggered live this pass given the time budget — round one's own writeup already live-verified each of these individually and in detail.
Verification method
Booted native build-debug driver, admin login (fluffos/Mud@2026) —
clean on the first attempt. update /adm/daemons/logind as the real
privileged-action check (succeeded). goto /quest/kaifeng/zhengtang as
a targeted re-exercise of the make_inventory isolation fix. Two full
rapid reconnects, both clean. work/log/debug.log grepped for the
original error signatures (Bad argument 4, Wrong permissions,
F_SKILL) after the whole session — zero hits; all new log growth was
either harmless compile warnings or the already-documented yayi
content-gap trace. Driver killed by exact PID after testing; incidental
fluffos.o save-timestamp churn reverted before commit.
Files modified this pass
work/adm/simul_efun/file.lpc—cat()null-guard.
§7.100 sub-threshold instance (2026-08-20)
Found during the §7.100 tail-sweep (below the original 166-lib survey's
=100-occurrence threshold, never checked). 40 live
replace_program(ROOM); occurrences across 31 files: 26 standalone
room-file/heredoc-template lines (real .lpc room files,
data/group/groom/*.lpc, feature/up.lpc,
quest/kaifeng/qianyafang.lpc) plus 14 string-builder-embedded
occurrences (literal \n replace_program(ROOM);\n escape sequences
inside generated-code strings) across data/group/obj/ling.lpc,
data/group/obj/ling-pai.lpc, a garbled-filename duplicate/backup of
ling.lpc under data/group/obj/, and this lib's own room-building
tools u/island/obj/roommaker.lpc/u/island/obj/roommaker1.lpc (two
copies, both fixed — so newly-built rooms were inheriting the bug too).
A full post-fix grep confirms 0 live occurrences remain. Verified via a
clean native driver boot (zero new debug.log errors, port listening,
killed by exact PID after ~8s).
§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.
Round three (2026-09-04): shop purchase + 拜师 check
New angle vs prior rounds: live shop + 拜师. Native build-debug
driver, port 40133. First send is the English id (no GB/Big5 menu).
Admin fluffos/Mud@2026 (wizlist (admin); unused admin-password
AdminPw1 this pass). Lands at 世外桃源/REGISTER_ROOM as before.
拜师 — still no legal master (content gap, not a new bug)
Reconfirmed by source: no official NPC set("family", ...) outside
u/. apprentice itself is intact. Did not invent a master.
Programming bugs found and fixed this pass
1. is_admin() hardcoded to id island
(adm/simul_efun/object.lpc). Wizlist lists lost/island/
fluffos as (admin), and the login banner printed
目前权限:(admin), but is_admin() also required
query("id") == "island". clone of anything outside
/clone/gift and call both returned 你不能复制物品 /
你不能使用该命令. Aligned is_admin() with is_root():
SECURITY_D->get_status(...) == "(admin)" is enough. Live:
call me->set_temp(...) and clone /obj/example/chicken_leg
both worked afterward.
2. move() threw on a missing dest path (feature/move.lpc).
call_other(dest, "???") on /d/fy/fysquare (never shipped)
raised *call_other() couldn't find object and aborted the
caller. adm/npc/youxun.lpc create() does that move for the
master copy, so the first clone /adm/npc/youxun died at
载入失败. Added file_size + catch before the load; missing
dest now returns the existing destination unavailable
notify_fail.
3. message_vision() dest int 0 (adm/simul_efun/message.lpc)
plus youxun create() announcing after a failed move. After
(2), move() returned 0 but create() still called
message_vision, and environment(me) was 0, so efun
message() got dest int 0 (*Bad argument 3). Guarded
message_vision when environment(me) is missing, and only
announce in youxun create() when move("/d/fy/fysquare")
succeeds. Live: 游讯复制成功,放在这个房间。
4. F_DEALER/F_VENDOR listed missing vendor_goods files via
unguarded call_other (feature/dealer.lpc,
feature/vendor.lpc). youxun's catalog points at
/clone/gift/{feidan,feimao,kuangquan} (directory not shipped);
芳儿/makeupseller point at /d/fy/npc/obj/... (same missing
map). list after unlocking can_buy/youxun now prints an
empty catalog instead of throwing. Content gap left as-is.
Shop — paid buy verified live
Official town map /d/fy is still missing, so there is no organic
walk-up shop. Used the real F_DEALER NPC 游讯 (/adm/npc/youxun,
id youxun / you xun): list without the temp flag is the
designed refusal 我只卖消息不卖货; after
call me->set_temp("can_buy/youxun", 1) the catalog is empty
(missing gift files, skipped). Stocked one existing item
(clone /obj/example/chicken_leg, id chicken / 烤鸡腿, value
30) via call youxun->set("can_carry", 1) + give chicken to
youxun (clone accept_object accepts), funded with clone
/obj/money/silver (一两 = 100). buy chicken →
你从游讯那里买下了一根烤鸡腿. Inventory afterward: 六十四文铜钱
+ 烤鸡腿 (100 − 30×12/10 = 64; F_DEALER inventory markup
val_factor 12). In-session price math + item receipt both
confirmed.
Cloned example objects are not autoload; a relog after
call me->save() kept the character but dropped the chicken/coins.
That is the existing autoload design, not a new save bug. Driver
killed by exact PID after the pass. Player-save timestamp churn
left uncommitted.
深度功能测试(§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-04)— undefined macro and simul_efun gaps
- 3 file(s)
inherit F_SSERVER;and no header defines it (3 did not compile:syntax error, unexpected L_IDENTIFIER, expecting L_STRING or '(').#define F_SSERVER SSERVERininclude/globals.h(KB 04 §6.2,scripts/lpc_alias_macro.py). 0 still fail.
深度功能测试(§10.7,2026-10-05)— 任务表里的 .c 路径与任务守护进程的防护
scripts/lpc_dynamic_quest_guard.py:2 处 spread_quest() 调用(init_dynamic_quest() 的循环里)包进 catch(),缺失的任务物品或编译不过的房间只跳过那一个任务,守护进程照常加载、其余任务照常生成。
验证:adm/daemons/questd.lpc、adm/daemons/tongjid.lpc、quest/tongji/npc/zhuge.lpc、u/lost/cmds/questd.lpc和 cron 守护进程在新进程里加载(HEAD 一次,工作树三次,选房是随机的):HEAD 通过 5 个,工作树三次分别通过 5、5、5 个(共 5 个),无回退。
深度功能测试(§10.7,2026-10-06)— 编译警告整理
scripts/lpc_warnings.py fyzfqyy --fix:无用局部变量 476 个、varargs 7 处、转义 56 处、nosave 函数 15 个改 protected,共改动 220 个 .lpc。HEAD 与工作树分别加载(新进程):211 -> 211 通过,无回退;scripts/lpc_audit_removed_locals.py HEAD 的 5 条候选都是声明被重建或同名 efun(time())。手工:adm/daemons/logind.lpc get_id() 的 string ip = query_ip_number(ob); 只被一段注释掉的站点检查读,删去。启动时警告 145 -> 0;新进程登录(英文名、新人物确认、中文名提示)正常。
深度功能测试(§10.7,2026-10-06)— 与 zhonghua2 同源的三处编译警告
include/npc/indian.lpc与masia.lpc共用全局名ma_sname/ma_pname;两个头文件被同一个守护进程(npcd等)一起包含时,后包含的印度名表覆盖马来名表,generate_ma_name()生成的是印度名字。印度表改名in_sname/in_pname(KB 04 §6.10)。cmds/std/team/swear.lpc:结义失败提示被多余的;截成两句,fail只剩"……可惜现在有人不在,$N",后半句"的提议只好作罢。"丢了;接回去。
验证:改动的文件和包含 npc/indian 的守护进程在 HEAD 与工作树分别加载(scripts/lpc_listcheck.sh,新进程),无回退。
- 2026-10-10:编译警告第二轮(按驱动报告逐条修):按位 & 改逻辑运算 0 处,返回类型/原型 0 处,NPC+F_UNIQUE 的 init() 0 个,带初始化的未用局部变量 2 个,只在 #if 分支用的声明移进分支 0 个文件;改动 1 个文件,HEAD 与工作树各载入一次无回退(1 objects; HEAD PASS 1, tree PASS 1; regress 0; newly loading 0),这些文件的警告 1 -> 0。
- 2026-10-10(续):第二轮编译警告整理(
lpc_fix_unused_init.py)删掉了只在不启用的#if分支里用到的局部变量声明(如include/net/ftpdsupp.h中#ifdef GUEST_WIZARD_FTP分支的file),启用该选项时会编译失败;声明已放回所用的分支里,工具已改为跳过这种情况(交给lpc_move_decl.py)。
深度功能测试(§10.7,2026-10-11):dns_master 空 if
adm/daemons/network/dns_master.lpcquery_services():if (! (mud_svc[mud]["tell"/"finger"] & SVC_KNOWN)) {里只有#if PREF_X & SVC_TCP … #endif,选项关闭时 if 体为空(“无副作用”警告);把#if/#endif挪到 if 外面(KB 04 §6.10,2026-10-07 那次扫描漏掉了! (带空格、大括号另起一行的写法)。载入无回退。
深度功能测试(§10.7,2026-10-11):dns_master 空 if
adm/daemons/network/dns_master.lpcquery_services():if (! (mud_svc[mud]["finger"/"tell"] & SVC_KNOWN))块里只有#if PREF_X & SVC_TCP … #endif,选项关闭时 if 为空(“无副作用”警告报在下一句);把#if/#endif挪到 if 外面(KB 04,2026-10-07 那次扫描漏了! (加括号换行这种写法)。载入无回退。
- 2026-10-14:新驱动(FluffOS 970d9f09)报
Float value truncated to int(#1426)。1 个文件 4 处:赋值、初始化、return 改写成to_int(...)(值不变,只是写明截断)。改动的对象新进程各载入一次,无回退(scripts/lpc_fix_float_trunc.py,KB 04 §6.10)。 - 2026-10-14:同一次重扫的其余 6 条:
std/room/room.lpc覆盖的delete()写成void,而feature/dbase.lpc/include/dbase.h是int,房间里delete()的返回值一直是 0;改int,默认分支return ::delete(idx),自管的三个字段返回 1。data/group/obj/ling(-pai).lpc和两个 roommaker 的第一张special_props表是死声明(之后的代码只读第二张),删去;NAME_D宏重定义前加#undef。改动对象新进程各载入一次,无回退(u/island/topten/toptend.lpc、ran_name/test_npc.lpc本来就编译失败,未动)。
其他体系的属性名(2026-10-15,KB 06 §7.241 第三类,--any-file)
6 个文件(技能、绝招、兵器、书籍、区域 NPC 等)来自侠客行体系(qi/jing/neili),而本库人物是 gin/kee/sen/force:receive_damage("qi", ...) 报 伤害种类错误,query("neili") 永远为 0。按 qi→kee、jing→sen(本库学习/读书指令消耗的就是它)、neili→force、max_neili→max_force、jiali→force_factor 改名(scripts/lpc_port_es_props.py --any-file)。
find_player() 只认在世界里的身体(2026-10-15,KB 07 §8.26)
simul_efun 的 filter_player() 加上 environment(ob):注册中途断线留下的、不在任何房间的身体不再被当成玩家,两个以上时 find_player() 不会再报 The player(<id>) has existed in the world.(wllz3 实测过的问题)。本库若注册流程不会留下带玩家 uid 的身体,这一改动不改变行为。
NPC 带着本库没有的物品,载入失败(2026-10-15,KB 06 §7.73)
2 个文件、3 处在 create() 里 carry_object("<本库没有的文件>")->wear()(或 wield()、set_amount()):carry_object() 得 0,接着的调用报 Bad argument 1 to EFUN call_other(),NPC 根本载入不了,该有它的房间里就少了这个人。多是从别的系统搬来的 NPC 用了原系统的物品路径(最常见:/d/fy/npc/obj/wch_skirt、/d/fy/npc/obj/yafu、/d/fy/npc/obj/sawei)。每处改为 { object carried_ob = carry_object(...); if (carried_ob) carried_ob->wear(); }(scripts/lpc_guard_carry_object.py):NPC 照常出现,只是不带这件东西;文件补回来(或是虚拟对象)照样会带上。载入检查:改动的文件改前能载入 0 个,改后 2 个(2 个原来载入不了),没有退步。
技能基类丢了“预备武功”那一段(2026-10-19,KB 06 §7.262)
feature/skill.lpc 有 skill_map/map_skill(),却没有预备武功(prepare_skill)这一块:变量 skill_prepare、prepare_skill()、query_skill_prepared()、query_skill_prepare()。来自 xkx 系列的 NPC 在 create() 里调用 prepare_skill("cuff", ...),于是 Undefined function prepare_skill 整个 NPC 载入不了。从同系的 xkx100 把这一块原样补回(声明加在 skill_map 后面,函数加在文件末尾),受益 NPC 5 个:quest/kaifeng/npc/tufei2、quest/kaifeng/npc/tufei3、quest/kaifeng/npc/tufei4、quest/kaifeng/npc/tufei5。(scripts/lpc_transplant_function.py)
区域物件的零碎修正(2026-10-19,KB 06 §7.267–§7.271)
adm/simul_efun/file.lpc补上同系列(fy3dz、fy3xd)的write_file2():adm/daemons/brd.lpc和订做衣服、打铁的 NPC 调用它,之前编不过
逐个物件与 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 文件。
member_array('/', str) 改为 strsrch(str, "/"):字符字面量的 member_array 按字节搜索(2026-10-20,KB 06 §7.283)
member_array('/', str) 里的 '/' 是整数,驱动按 UTF-8 字节搜索,返回字节偏移(带第三个参数时起点也是字节);最新的 FluffOS(923cdbc0)在字符串里有非 ASCII 文字时,对每个调用点警告一次(Warning: member_array(int, string) searches BYTES)。而 str[0..idx-1] 按字符切,中文字符串会在错误的位置截断。改为 strsrch(str, "/")(找不到同样返回 -1,按字符计数;scripts/lpc_fix_member_array_char.py,JSON 编码器等少数几处手改)。改动:/cmds/arch/sameip.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,共 1 处)。改动:/adm/daemons/combatd.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)。
get_config(__MUD_PORT__) 经旧版 runtime_config.h 得到字符串(2026-10-20,KB 06 §7.302)
本库的 include/runtime_config.h 是老 MudOS 的编号(整数设置从 15 起,本驱动从 256 起),get_config(__MUD_PORT__) 读到的是另一项设置(字符串),(int) 又只是编译期标注,于是 socket_bind(fd, LOCAL_PORT()) 报 Bad argument 2 to socket_bind(),版本守护进程 port = get_config(__MUD_PORT__) + VERSION_PORT 是字符串相加。头文件自己的注释写明 get_config(__MUD_PORT__) == __PORT__,所以代码里的这个调用(连同外面的 (int) / to_int())改成了驱动的预定义 __PORT__(scripts/lpc_fix_mud_port.py)。改动:/include/getconfig.h(1 处)。
closed 守护的心跳每秒调一次不存在的 versiond(2026-10-20,KB 01 §1.3(c))
closed.lpc 的 heart_beat() 以 if (! VERSION_D->is_version_ok()) return; 开头,本库没有 /adm/daemons/versiond:有人在闭关时,控制台每秒一条 call_other() couldn't find object '/adm/daemons/versiond',闭关的后续处理(load_all_users())也永远走不到。改成 if (find_object(VERSION_D) && !VERSION_D->is_version_ok())(KB 01 的写法:没有版本守护就当版本正常)。加载检查 OK。
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、/std/char/npc2.lpc(共 2 个文件)。
refresh(retask):动词函数不返回 1,搬动或销毁带动作的物件时报错(2026-10-21,KB 06 §7.339)
管理员扫描里 refresh 在重新分布使命之后报 Illegal to move or destruct an object (/questobj/...) defining actions from a verb function(refresh) in object(/obj/user#...) which returns zero.:main() 以第二条 message() 结尾、没有 return,答 0,而 TASK_D->init_dynamic_quest(1) 销毁了给玩家定义过动作(init() 里的 add_action)的使命物件:驱动只在动词答非 0 时才允许这样搬动或销毁,否则它接着遍历的动作表会悬空;答 0 还会让解析器在指令做完之后再补一句“什么?”。main() 末尾加 return 1;(同系已经返回 1 的 11 个同名文件没有动)。
socket:dump_socket_status() 在本库没有(2026-10-21,KB 06 §7.291)
管理员扫描里 socket 指令(/cmds/island/socket.lpc)编译不了:write(dump_socket_status()); 用的是 MudOS 有、本驱动没有的 efun。2026-10-20 的补丁只按名字找了巫师目录里的同名指令,这一条在 cmds/bos、cmds/hufa、cmds/island、cmds/ser 这类目录里;用 scripts/lpc_add_sefun.py dump_socket_status 在 /adm/obj/simul_efun.lpc 末尾补了一个由 socket_status() 构造表格的 simul_efun(没有 sockets 包的构建,比如 WASM,只打印表头)。指令 HEAD 编译失败,现在通过。
坐骑 shape:/cmds/usr/skills 不存在(2026-10-21,KB 06 §7.344)
obj/npc/pet.lpc 的 do_shape() 末尾 printf("/cmds/usr/skills"->pet_skill(this_object()))。本库的 skills 在 cmds/skill/skills.lpc(pet_skill() 就在那里),改成 /cmds/skill/skills。
调用了、但这个库自己的守护进程里没有的函数(2026-10-22,KB 06 §7.354)
MACRO->函数() 调用的函数在这个库的守护进程里不存在:call_other() 对不存在的函数不报错、只返回 0,所以这些功能(时间显示、昼夜事件、名字检查、价格文字……)一直没起作用。同一血统另一个库的同名守护进程里有这些函数,原文照抄到本库守护进程末尾(scripts/lpc_port_function.py;调用处传的参数个数、函数体用到的函数 / 全局变量 / 宏 / 字符串键都在本库里有,已核对;守护进程在 HEAD 和工作区都能加载,每个函数用固定参数各调用一次:HEAD 返回 0,现在返回正常的值):/adm/daemons/chinesed.lpc ← aoxiangtianji:chinese_month()(1 处调用)。
(: 函数 :) 指针指向对象自己没有定义的函数(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。 还剩 1 个函数没有补(other 1):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/cmds/imm/help2.lpc:confirm_l_choice。
log/ 下的日志子目录没有人建:写日志的 write_file() / log_file() 报错(2026-10-22,KB 06 §7.358)
这个库的代码往 log/ 的 1 个子目录写日志:log/doc/register(cmds/usr/help1.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 的实测表。
长度检查按字节写,旁边的提示按汉字写:4 处(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 你好吗)。本库 4 处(2 个文件):if ((strlen(name) < 2) || (strlen(name) > 40)) {(/adm/npc/caifeng.lpc:163)。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 区间 7 个文件;channeld 同盟 / 门派标题 1 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。
中文名 / 验证码仍按 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。
无参数时命令对 0 的调用(2026-10-27,KB 06 §7.336 Also)
巫师/管理员命令在通过权限门之后仍会把 0 交给 sscanf / read_file / find_living 等。lpc_fix_bare_arg.py 在首次使用参数前加上 if (!arg)(或 help(me) / GetHelp())。本库本批改动见该提交。
深度功能测试(2026-10-27,§6.10 未知 pragma save_binary/optimize)
删除本库中 FluffOS 不认的 #pragma save_binary / #pragma optimize… 行。