info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
游戏内标题为 "REVIVE OF ULTRA HELL(BLOOD & MAGIC) FROM 1999.11.13"(作者自称"doing"),是本项目收录规模最大的金庸题材 mudlib 之一(超过 7000 个 LPC 文件),改编自金庸小说《侠客行》,建立在"东方故事Ⅱ"(Eastern Story II)引擎之上,出生地扬州客店由原著角色戚长发坐镇。它也是本项目里"地狱"/Doing 血统家族的源头:`zjdy2008wzb`、`zjdyaryl`、`zjdywzb`、`zjdyzj` 都与它大量复用同一份地图内容(字节级比对显示 67%-88% 的地图重合),`yhwhpublicfi`(炎黄武魂)的 `master.lpc` 文件头明确写着自己是在这份档案基础上修改而来,`zjmudhell`(指尖MUD)则保留了 67% 相同的地图,却把核心系统整体重写成配合自定义手机 App 协议的实现。新角色要经历一场真正的"投胎"仪式而非简单的选性别流程:注册邮箱并确认、走到不同 NPC 面前选择品性(其中一支的开场白直接点名郭靖、萧峰)、途经阎罗殿(十殿阎罗、牛头马面、地藏王坐镇)、在忘忧池中随机洗四项天赋,最后从包含慕容世家、欧阳世家、段氏皇族、关外胡家等《天龙八部》相关出身在内的 18 个地名中选择投胎地。47 块留言板覆盖了少林、武当、明教、逍遥派、天地会等几乎金庸小说宇宙里所有主要门派,并不局限于单一小说。
English
The in-game title is "Revive of Ultra Hell (Blood & Magic) from 1999.11.13" (the author calls themselves "doing") -- the largest Jin Yong-themed mudlib in this project by file count, at over 7,000 LPC files, and the root of a whole "Hell"/Doing lineage: this project's zjdy2008wzb, zjdyaryl, zjdywzb, and zjdyzj all reuse substantially the same room-tree content (a byte-level, line-ending-normalized comparison found 67-88% of hell's own map reused across those four), yhwhpublicfi's own master.lpc header states it was built as a modification of this exact archive, and zjmudhell (Fingertip MUD) carries a closely related map (67% identical) while rewriting every core system around a custom mobile-app protocol. The game's own rules text names its source precisely -- adapted from Jin Yong's "Ode to Gallantry," built atop the "Eastern Story II" mudlib -- and the starting Yangzhou inn is staffed by Qi Changfa, a named character from that novel. New characters go through a genuine reincarnation ritual rather than a plain character-creation menu: register an email, confirm, approach one of several NPCs to choose a moral disposition (one path's NPC opens by invoking Guo Jing and Xiao Feng by name), pass through the Court of Hell (the Ten Yama Kings, Ox-Head and Horse-Face, Ksitigarbha presiding), bathe in the River of Forgetfulness to randomize four core stats, then choose a birthplace from an 18-option list that includes the Demi-Gods-and-Semi-Devils-derived Murong, Ouyang, Duan-imperial, and Hu-clan origins. 47 bulletin boards cover nearly every major sect across multiple Jin Yong novels rather than a single source.
README
内容亮点
- 这是"地狱"/Doing 血统家族(
zjdy2008wzb/zjdywzb等档案都同源,yhwhpublicfi/炎黄武魂的master.lpc文件头也明确写着自己是在 这份"hell"档案基础上二次修改而来);zjmudhell(指尖MUD)的地 图也和这份档案逐字节相同,但核心系统档案被完全重写成配合自定义 手机 App 协议的实现,是"地图沿用、引擎重做"的一个特例 的原始档案,超过 7000 个 LPC 文件,是本项目里规模最大的金庸题材 泥潭之一。游戏规则文本里明确写着"本游戏改编自「侠客行」,原是建 立在「东方故事Ⅱ」MUDLIB 上"——不是笼统的"金庸题材",而是有明确 的原著出处(金庸小说《侠客行》),出生地扬州客店就有戚长发("躺 尸剑门传人")等原著角色坐镇。 - 独特的"投胎"新手引导,仪式感比常见的"选完性别就直接进游戏"重得 多:
register <email>登记邮箱 →decide确认 → 走到不同 NPC 跟前用out选择品性(如"光明磊落"一支的陆天抒,开场白直接点名 "郭靖、萧峰"两位金庸主角)→ 到阎罗殿(十殿阎罗、牛头马面,地藏王 端坐大堂,气氛渲染和游戏"地狱"主题呼应)→wash跳入"忘忧池"随 机洗四项天赋 →born <地名>正式投胎。此前score等指令都会提 示"还没有出生呐"。 born的目的地清单(look paizi查看)一共 18 个选项,除了苏州、 杭州等常见地域外,还有"慕容世家""欧阳世家""段氏皇族""关外胡家" 四个直接对应《天龙八部》里慕容复、欧阳锋、大理段氏、丐帮相关家族 的特殊出身,是有心思的金庸世界观还原。- 留言板系统一共 47 块,覆盖了金庸小说宇宙里几乎所有主要门派:少林、 武当、全真、桃花岛、明教、嵩山、泰山、青城、日月神教、灵鹫宫、星 宿派、慕容家、神龙教、血刀门、逍遥派、天地会、雪山寺、侠客岛…… 不只取材自单一小说,而是把多部金庸作品的门派体系揉进了同一个世 界观,这一点在同类"金庸题材" mudlib 里也是比较突出的。
- 角色类型菜单(1-5,直接回车默认均衡型)搭配姓氏+名字分离输入, 和同家族的
zjdy2008wzb/zjdywzb一致。 - 本次修复过程中新发现并记录进 AGENTS.md 的两个 bug 类别(§7.61
message()的exclude参数缺省值、§7.62check_legal_id()对 空字符串的循环失效),后来都在其它档案里复用了同样的修法。深度功 能测试(见下)又额外发现两个阻断性的 bug——MESSAGE_D未加保 护呼叫、command_hook权限降级——两者任一未修都会让全新玩家完全 无法完成注册。
注册流程
英文 id(3-10 个小写英文字母)→ 确认建立(y/n)→ 中文姓氏(0-2 个汉
字,可留空跳过)→ 中文名字(1-2 个汉字,姓名合计至少 2 个汉字)→
管理密码(≥5 字元)→ 确认管理密码 → 普通密码 → 确认普通密码 → 角色
类型(1-5,直接回车默认均衡型)→ 性别(m/f)→ 进入游戏世界。进入游
戏后需要依次完成"投胎"仪式:register <email> 注册邮箱 → decide
确认 → 走到某位 NPC 跟前 out 选择品性 → wash 洗天赋 →
born <地名>(地名清单见 look paizi)正式投胎,此前 score 等命
令会提示"还没有出生呐",这是正常的游戏设计,不是 bug。
本次修复的关键 bug
adm/daemons/logind.lpc的check_legal_id():while (i--)循环 对空字符串(strlen(id)==0)根本不会执行循环体,直接落到return 1,把空的英文 id 当作合法输入接受。后续clone/user/login.lpc的query_save_file()对空 id 取my_id[0]得到整数 0,传给sprintf("%c", 0)崩溃退出,报错信息 和真正的 bug 位置相距甚远。已在循环前显式拒绝空字符串(新增 AGENTS.md §7.62)。adm/simul_efun/chinese.lpc的is_chinese():沿用旧版 GBK 字节 区间判断,在这个驱动上strlen()按字符计数、str[i]是 Unicode 码点而非原始字节,真实的中文姓名永远无法通过检测。已改为码点区 间判断(0x4e00-0x9fff,AGENTS.md §8.1)。adm/daemons/logind.lpc的check_legal_name()以及adm/daemons/named.lpc的invalid_new_name():三处独立的 字节数长度界限(假设每个汉字占 2 字节 GBK),在字符计数的strlen()下全部偏大一倍——姓氏/名字各自的长度界限、姓名合计的 最短长度界限、以及invalid_new_name()内用于查重的滑动窗口 (name[i..i+3]/name[i..i+5])都按 AGENTS.md §8.1 的既定手法减 半修正。adm/simul_efun/message.lpc的message():3 参数调用时exclude是未初始化的整数 0,直接传给efun::message()导致Bad argument 4 to EFUN message()——不只 影响tell_room()(已知的 §7.12 形状),channeld.lpc的do_channel()广播和questd.lpc的collect_all_quest_information()心跳都各自独立触发同样的崩溃。 已直接在message()包装函数内加exclude || ({})兜底(新增 AGENTS.md §7.61)。clone/user/user.lpc的accept_kill():is_killing(ob)传入 物件而is_killing()期望字符串 id(AGENTS.md §7.50,第四个独 立发现同一 bug 的血统),导致整个玩家身体类无法编译。已改为is_killing(ob->query("id"))。adm/daemons/versiond.lpc(~2200 行的版本同步守护进程):纯 socket 功能在 WASM 下无法编译,按"禁用整个文件的入口点"方式清空 为 no-op(AGENTS.md §7.52,和zjmudhell/shujian3的同名文件 近乎字节相同),共 13 处:in_server()/connect_server()/send_command()/send_client_pending_msg()/syn_finish()/in_listen_callback()/in_write_callback()/in_close_callback()/cmd_close()/send_pending_msg()/send_result()/remove_connection()/clear_syn_info()内的socket_close()分支。整个文件因为散落各处的socket_*调用无法编译,运行时会 导致logind.lpc的logon()崩溃(*No program in object '/adm/daemons/versiond'!),断开每一个新连接。- 本地存档目录
log/nosave/在这份档案里不存在,导致每个新连接一 进来就在logon()写日志时报错断线。已本地创建该目录。
深度功能测试(第二轮)新发现的两个阻断性 bug
此前的验证只做到"看到世界入口房间",从未真正走完新玩家的"投胎"流
程;本轮完整实测后发现两个此前从未触发过的严重 bug,任一未修都会让
全新玩家完全无法完成注册(细节见 NOTES.md 的"深度功能测试"一
节):
adm/daemons/logind.lpc的check_ok()(每次密码校验通过后都会 执行)未加保护地呼叫MESSAGE_D->find_chatter(...)。MESSAGE_D(聊天/UDP 精灵)自己的create()有原始socket_create()/socket_bind()呼叫,WASM 下编译不过,导致密码验证成功之后连线 直接静默断开,永远看不到欢迎信息。已加find_object(MESSAGE_D)保护(AGENTS.md §1.3(c),yanhuangwuhun/yhyxs已知同类 bug 的 第三个实例)。feature/command.lpc的command_hook声明为private nomask,在这个驱动上继承后会从private降级为DECL_HIDDEN,导致add_action("command_hook", "", 1)这种"捕获 所有指令"的注册方式对ORIGIN_EFUN(其它物件用command()efun 发起的呼叫)静默失效(AGENTS.md §8.3a)。这份档案的"投胎"引导全 部靠 NPC 内部command("say/tell/nod ...")说话实现,所以这一个 bug 直接卡死了register/decide的每一句 NPC 回应——玩家输入register 邮箱之后add_action正确匹配、不报"什么?",但水笙 一句话也不说,表现上和网络问题一模一样。已去掉private,保留nomask。
管理员账号 / Admin account
- id:
fluffos - 密码 / password:
Mud@2026 - 管理密码 / admin password:
Mud@2026Adm - 权限 / level:
(admin)
管理员名单存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常注
册流程创建,"目前权限:(admin)" 已在游戏内确认显示正确。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。
本地运行
cd libs/hell
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40114。
NOTES · 移植与修复记录
WASM 修复摘要(迁移自 meta.json 的 group_note)
Doing 血统的大型金庸题材 mudlib(7000+ 个 LPC 档案),游戏内标题为 REVIVE OF ULTRA HELL(BLOOD & MAGIC) FROM 1999.11.13。修复的 bug:(1)缺失的本地 log/nosave/ 目录导致 logon() 期间每一个新连线都会断线;(2)check_legal_id() 的 while(i--) 循环会静默接受一个空的英文 id,之后对这个空字符串呼叫 sprintf("%c", my_id[0]) 就会崩溃(新增 AGENTS.md §7.62);(3)经典 §8.1 GBK 字节区间 is_chinese() bug;(4)三个各自独立的字节数没减半的长度界限 bug(check_legal_name 的姓氏/名字界限、姓名合并后的最短长度、以及 named.lpc 的 invalid_new_name() 滑窗查重检查)都按已确立的 §8.1 减半模式修复;(5)§7.12 类的 message() exclude 参数 bug 就活在 message() 包装函式本身,不只是 tell_room()——channeld.lpc 的 do_channel() 和 questd.lpc 的 collect_all_quest_information() 各自独立崩溃(新增 AGENTS.md §7.61);(6)accept_kill() 里 §7.50 的 is_killing(ob) 物件/字符串不匹配 bug,是第 4 个确认的同类血统;(7)versiond.lpc 的 13 个碰 socket 的函式按 §7.52 掏空(和 zjmudhell/shujian3 那份几乎逐字节相同),修复了一个会让每个新用户在 logon() 时断线的崩溃。管理员账号(fluffos/Mud@2026,管理密码 Mud@2026Adm)通过真实注册流程 + adm/etc/wizlist 播种,游戏内"目前权限:(admin)"显示确认生效。完整的注册→look→score→quit 流程在排版格式化前后各验证过一次,用的是真实中文名字。
深度功能测试(第二轮,2026-08-03)
本轮不再满足于"注册→look→score→quit"的浅层冒烟测试,而是完整走了 一遍这份档案自己独特的"投胎"新手引导流程,并在过程中发现并修复了两 个会让游戏完全无法正常游玩的严重 bug——此前的验证记录只覆盖到 世界入口房间,从未真正触发过这两处代码。
发现并修复的 bug
1. MESSAGE_D->find_chatter() 在 check_ok() 里未加保护呼叫
(新增 AGENTS.md §1.3(c) 条目,yanhuangwuhun/yhyxs 已知同类 bug
的第三个确认实例):adm/daemons/logind.lpc 的 check_ok()——每一
次密码校验通过后都会执行的函式——无条件呼叫
MESSAGE_D->find_chatter(...)。MESSAGE_D
(adm/daemons/network/messaged.lpc)自己的 create() 里有原始的
socket_create()/socket_bind() 呼叫(一个 UDP 聊天/跨服精灵),
在 WASM 下完全编译不过。未加保护的呼叫会抛出"*No program in object
'/adm/daemons/network/messaged'!",让 check_ok() 执行到一半就中
止——早于 make_body()/enter_world(),也就是说每一次密码验证
成功之后,连线都会直接静默断开,永远走不到欢迎信息或注册房间。
已仿照 yanhuangwuhun/yhyxs 已经确立的修法,加上
if (find_object(MESSAGE_D)) { ... } 保护。
2. feature/command.lpc 的 command_hook 声明为 private(
AGENTS.md §8.3a,第一次在这份档案上确认,且是目前记录里症状最隐
蔽的一次):private nomask int command_hook(string arg) 在这个驱
动上一旦被继承就会从 private 降级为 DECL_HIDDEN,导致
add_action("command_hook", "", 1) 这种"捕获所有指令"的注册方式
静默失效——但只对 ORIGIN_EFUN(也就是其它物件透过 command()
efun 发起的呼叫)生效,玩家自己直接敲的指令走 ORIGIN_DRIVER,不
受影响。这份档案独特的"投胎"新手引导——register/decide/
wash/born——全部是通过 d/register/npc/shuisheng.lpc 的
do_register()/do_decide() 内部呼叫 command("say/tell/nod
...") 来实现 NPC 说话的,也就是说这一个 bug 直接卡死了每一个
全新玩家注册流程的第一步:玩家输入 register 邮箱地址 后,
add_action 本身正确匹配、没有报"什么?",但水笙一句话也不会说,
连她自己被动触发的 greeting()(新手一进房间的欢迎语)也同样哑火
——表现上和网络延迟或连线故障一模一样,很容易被误判为环境问题而
不是代码 bug。真正的诊断线索藏在驱动自己的日志里,而不是玩家看到
的画面:apply() with insufficient permission: ... function:
command_hook, origin: efun, needs: private, has: hidden,时间戳
和指令发送的瞬间精确对应。修复方式和 §8.3a 记载的完全一致:去掉
private,保留 nomask。
两处 bug 一起意味着:在这次修复之前,这份档案的 WASM 打包版本任何
一个全新玩家都无法真正完成注册——check_ok() 的崩溃会先一步掐断
连线;就算侥幸绕过(比如管理员账号已经存在存档,走的是不同分支),
"投胎"引导流程本身也会在 register 这一步彻底哑火。此前的验证记录
只做到"看到世界入口房间"就停了,从未真正把这两条路径走通过。
完整验证:从注册到进入游戏世界
用一个全新账号(非既有的 fluffos 管理员存档)在浏览器环境 (Playwright 驱动的真实 Chromium,不是脚本化的 telnet 客户端——排查 过程中发现脚本化客户端对这份档案的编译延迟计时特别敏感,容易把"driver 正忙着编译"误判成"指令没有响应",回头改用真实浏览器环境后同样的操 作序列每次都干净复现)完整走通:
register [email protected]→ 水笙点头确认,说明邮箱地址、警告 不做 mail 验证。decide→ "好了!你的email地址已经注册了!现在快去附近选你的品 质吧。"- 向东走到"桃源竹屋",见到陆天抒——他的开场白直接点名"郭靖、萧峰" 作为"光明磊落"这个品性的代表人物,是金庸小说里两位主角的直接互文。
out确认选择这个品性,自动被送到"阎罗殿"——十殿阎罗、牛头马面、 地藏王端坐大堂的场景描写,气氛渲染得相当到位,和游戏标题"终极地狱 之地狱无门"的地狱主题呼应。地藏王会主动递上"新手入门必读"。look paizi看到投胎目的地清单,一共 18 个选项——除了苏州、西域、 杭州等常见地域外,还有"慕容世家""欧阳世家""段氏皇族""关外胡家"这 四个直接对应《天龙八部》里慕容复、欧阳锋、大理段氏、丐帮相关家族 的"出身"选项,是很有心思的金庸世界观还原,不是套模板的通用武侠背 景。wash跳入"忘忧池"随机洗一组四项天赋(膂力/悟性/根骨/身法)。born 扬州人氏完成投胎,正式进入游戏世界,出生在扬州客店,店小 二、「滑不留手」游讯、「宰人不用刀,愿者上钩」戚长发("躺尸剑门传 人")三个 NPC 同时在场——戚长发这个称号直接对应金庸小说《侠客行》 里的角色,游戏规则文本里也明确写着"本游戏改编自「侠客行」,原是建 立在「东方故事Ⅱ」MUDLIB 上的一个 MUD"——比 README 原本笼统的"金庸 题材"要精确得多,这份档案有自己明确的、可考据的原著出处。score显示完整角色面板:称号"普通百姓"、"你是扬州人氏,天性光明 磊落,还没有拜师",四项天赋 20/20/20/20,气血食水槽全满,战斗数值 已初始化——和选择的出生地、品性一一对应,没有发现数值错配。board列出这份档案的留言板系统,一共 47 块,几乎覆盖了金庸小说里 所有主要门派/阵营:少林、武当、全真派、桃花岛、丐帮(暗含)、明教、 嵩山、泰山、青城(五岳剑派对应《笑傲江湖》)、日月神教、灵鹫宫、 星宿派、慕容家、神龙教、血刀门、逍遥派、天地会、雪山寺、侠客岛 等——这不是单一某部小说的题材,而是把金庸武侠宇宙里的多部作品揉进 了同一个世界观,是这份档案区别于其它"金庸题材" mudlib 的一个具体、 可验证的特征,值得写进 README 的内容亮点。quit干净退出,"欢迎下次再来!","【系统报告】离线精灵:浮浮 (fluffos)离开游戏了。",无残留错误。
已知但不是本次范围内 bug 的观察
重新登录测试时撞上了"您要将另一个连线中的相同人物赶出去,取而代之
吗?(y/n)"——是 check_ok() 里正常的"同一角色已有一个连线存在"保
护逻辑(旧连线的 quit 和新连线的重新登录之间存在一个正常的竞态窗
口),不是 bug,是预期的多重连线保护设计,符合 AGENTS.md §10.7 第 5
条记载的"quit 保留窗口"现象。
未覆盖范围(诚实说明,未做代码审查冒充实测)
本轮预算集中在把"投胎"全流程和两个阻断性 bug 排查清楚,没有走到:
战斗(木人训练木人在 d/guanwai/,离出生点扬州有一段路)、拜师、
经济系统/商店、以及门派加入。这些留给下一轮深入测试;目前的验证边
界到"进入游戏世界 + score + board + quit"为止,如上所述。
深度功能测试(第二轮,2026-08-18)——发现并修复两个真实 bug:messaged.lpc 的 socket_bind() 崩溃、eval-cost 过低
补完上一轮留下的战斗/门派测试,过程中发现并修复两个真实 bug。
- 发现并修复:
adm/daemons/network/messaged.lpc的startup_udp()第一次被触发时崩溃(§7.52 类,本档案自己已经确认过的同一类问 题的漏网之鱼):用巫师账号第一次执行goto指令时(触发messaged.lpc首次懒编译/初始化),撞上执行时段错误:*Bad argument 2 to socket_bind(); Expected: int Got: "10"。追根溯源:create()里my_port = LOCAL_PORT() + MESSAGE_PORT;,LOCAL_PORT()宏是(int) get_config(__MUD_PORT__)——这个(int)转型只在编译期 有效,get_config()实际运行时返回的不是数字(这个驱动版本上这 个 config key 的取值行为和预期不一致),所以LOCAL_PORT()真 正返回的是一个空字符串,"" + 10(LPC 里字符串 + 整数是字符串 拼接,不是数值相加)就得到了字符串"10",传给要求int类型 的socket_bind()直接崩溃。这份档案的adm/daemons/versiond.lpc在更早一轮(2026-07-31)就已经因为完全同一类"socket 包在这个驱 动环境下不可用"的问题被按 AGENTS.md §7.52 掏空过 13 个函式,但messaged.lpc(同样是碰 UDP socket 的收发信件精灵)当时被漏掉 了。修复:按同一手法把startup_udp()掏空成直接return 0(跨 MUD UDP 消息在这个环境下本来就不可用,让它安安静静地做无害的 no-op),顺手给send_udp()加了!socket_id的保护(原本没有 判断socket_id是否真的建立成功就直接呼叫socket_write())。 现场验证:重启全新驱动进程,goto现在干净执行,debug.log里不再出现任何socket_bind/Bad argument记录。 - 发现并修复:
config.fluffos的maximum evaluation cost撞上 §7.90 已确立的"后台任务精灵"变体:debug.log里出现两条Eval interrupted: ... cost limit reached, limit: 700000 usec→*Too long evaluation. Execution aborted.,调用点分别是d/xueshan/obj/yinlun#96和kungfu/class/generate/questnpc#275——都是这份档案自己非常活跃 的后台"任务精灵"系统(游戏内持续能看到"【系统报告】任务精灵: 进程(...)创建了一个任务"的滚动播报)动态生成 NPC/物件时的冷编译 开销,不是玩家直接触发的。按 §7.90 已确立的标准修复,从 700000 (本项目模板默认值)提到 5000000(本项目内 30+ 档案已经在用的同 一个值)。现场验证:重启后驱动空转约 30 秒(任务精灵系统持 续在后台生成任务),debug.log全程零cost limit reached记录。 - 战斗测试:练功房的木人(
clone/npc/mu-ren.lpc)继承自inherit/char/fighter.lpc的accept_fight()/accept_hit(), 两者都要求ob->query("combat_exp") >= 12000才允许练功 ("你这点身手还不足以和木人练功。")——一个全新角色的combat_exp默认是 0,永远达不到这个门槛。这不是一个可以直接判 定为程序 bug 的发现(combat_exp门槛属于内容/数值设计范畴,按 本项目既有的"深度测试范围限定在程序 bug"原则不去动它),只是如 实记录:这个具体的木人可能是给中高阶角色用的进阶陪练目标,不是 绝对新手的第一个练功对象,真正给新手用的陪练(如果存在)需要下 一轮另外去找。 - 门派加入、经济系统仍未测试:本轮时间预算集中在排查上面两个 真实 bug,没有再去找门派拜师的 NPC 或商店,留给下一轮。
深度功能测试(第四轮,2026-08-19)——补完门派加入与经济系统测试
本轮专门针对第二轮/第三轮明确留白的两个系统:门派加入(拜师)与经济系统 (商店买卖)。检查清单上的既有 bug 条目(§7.90/§7.111/§7.112/§7.113/§7.114/ §7.115)全部做了逐项复查,均已在此档案上确认修复到位或本来就不适用,无异常。
门派加入(拜师)——机制本身工作正常,无 bug
- 找到丐帮的招募 NPC
kungfu/class/gaibang/bai.lpc(白世镜,执法长老),藏 在/d/gaibang/mishi(密室)——从/d/city/gbxiaowu往西进入undertre(树洞下)再往下到chuchang(储藏室)再往西才能到,用巫师goto直达 测试。 bai <对象>(cmds/skill/bai.alias指向apprentice.lpc)的完整拜师流 程验证:
- 拒绝路径:初始角色 str=14(默认值)时,bai bai shijing 正确触
发 attempt_apprentice() 里的门槛检查,NPC 回应"我们丐帮的武艺一向以
刚猛为主,小兄弟臂力太弱,似乎不宜学丐帮的功夫?"(str<26 的检查)。
- 用 call me->set_skill("force", 320) 把内功技能设到刚好越过第二道门
槛(query_skill() 非 raw 模式返回值是 set_skill 存入值的一半,所以
需要设 320 才能让 query_skill("force")>=150),配合 str=30,再次
bai bai shijing 正确触发接受路径:"白世镜说道:好吧,希望小兄
弟能好好学习本门武功...白世镜决定收你为弟子...恭喜您成为丐帮的第十九
代弟子。"
- 两条路径都验证通过,bai/attempt_apprentice() 机制本身没有 bug——
和之前几轮在其它档案(niaoren、aoxiangtianji)上得出的结论一致。
- 测试完毕后已清理:call me->delete("family")、set("str",14)、
delete_skill("force")、set("title","普通百姓"),把 fluffos 管理测
试账号恢复到测试前状态(该账号本身就是一个跨轮次复用的巫师/管理员测
试身份,不是真实玩家存档;本轮验证后重启的驱动进程也确认了 family/
str 的清理确实落盘持久化)。
经济系统——sell/value 只在少数商人身上注册,确认是内容设计,不是 bug
- 最初误判为 bug(
feature/dealer.lpc混入类完整实现了do_list/do_buy/do_sell/do_value四个函式,但 78 个商人 NPC 里有 72 个init()只add_action了list/buy,没有sell/value),一度修复+提交+推送 (补全全部 69 个档案的add_action注册),并据此发起了一次跨档案的 118 个库、8,436 个档案的机械化清扫。用户在清扫落地前叫停,指出这更可 能是内容设计而非程序 bug——复查证实:本来就正确注册了全部四个指令的 6 个商人里,dangpuzhang(当铺掌)、chaofeng(老朝奉,古典白话小说 里典当行估价掌柜的专有称呼)两个名字本身就是当铺/估价类角色,不是随机 子集;这和 aoxiangtianji 档案独立发现的模式一致——普通商店只能买不能 卖,卖东西要去专门的当铺。结论:这是"只有当铺/估价类 NPC 才回收玩家 物品"的有意设计,不是程序 bug,已用git revert撤销hell这份档 案上的相关提交,未跨库执行清扫。教训记入项目记忆:不能仅凭"多数商人缺 少某个指令,少数商人有"就判定为遗漏 bug,需要先检查"有"的那一小撮是否 有主题/命名上的共同点,能说明这是有意为之的设计区分。
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 44 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
AGENTS.md §7.100 fix (2026-08-19): redundant replace_program(ROOM) landmine
Same corpus-wide bug as §7.86 above, but on the universal ROOM base
class ("/inherit/room/room" from include/globals.h) instead of
just boards — the batch-1-6 sweep's shape. Deleted 2,372 live
standalone replace_program(ROOM); lines under work/ via
fix_710_room.py, plus hand-fixed the room-building tool's
string-builder template (work/clone/misc/roommaker.lpc). 8 real
.lpc files under work/data/ checked for the known false-negative
class — none had the bug pattern. Remaining matches after the fix are
all pre-existing //-commented.
Verified: clean build-debug boot (zero new compile errors, zero
"cannot replace"/"cannot bind" in debug.log), live admin login
(fluffos/Mud@2026) into the game world, look/score/quit all
worked cleanly (the "还没有出生呐" score response is pre-existing
admin-account behavior, unrelated to this fix). Incidental
data/{login,user}/f/fluffos.o save drift from the login test was
reverted via git checkout HEAD before committing.
§7.30 uninitialized-mapping accessor sweep (2026-08-20)
Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage
bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2
via round-four testing): 5 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.
深度功能测试(第五轮,2026-08-24)——补完真实战斗测试,§10.7 收尾
前四轮已验证注册投胎、拜师门派、经济系统均干净通过,唯独"战斗"一
直只测过练功房木人(clone/npc/mu-ren.lpc),而它的 accept_fight()/
accept_hit() 要求 combat_exp>=12000,全新角色永远打不过这道门
槛——已在第二轮记录为内容/数值设计,不是 bug,但也意味着战斗机制
本身从未被真正打通过一次。本轮专门找一个新手够得着的、真正会打的
敌对 NPC 补上这一测试项。
- 用既有巫师账号
fluffos登录(跨轮次复用的管理/测试身份,非真 实玩家存档),goto /d/city/nandajie1(南大街,出生点客店往西 南方向不远,正常玩家步行可达)。 - 该房间刷新
d/city/npc/liumang.lpc(流氓,combat_exp=1000,attitude="peaceful")与liumangtou.lpc(流氓头,combat_exp=7000)——都继承自inherit/char/npc.lpc的默认accept_fight()/accept_hit(),没有像木人那样额外加combat_exp门槛判断,是真正"新手打得到"的敌对目标。 kill liu mang:NPC 正确应战("流氓说道:好!小王八蛋,咱们就 一决生死!"),随后进入完整的拳脚交锋回合——双方轮流出招、命 中/闪避/格挡判定、疲劳提示("你气喘嘘嘘")全部正常触发,一路打 到角色体力耗尽后触发自动逃跑机制,遁光传送到附近的当铺 (/d/city/dangpu)脱离战斗——是一次完整、真实的战斗到"逃跑" 结局的闭环,不是卡在开场或者中途崩溃。debug.log全程干净:整场战斗期间只有既有的懒编译Unused local variable/Unknown #pragma一类编译期噪音(这份档案启动 时一贯就有的背景噪音,跟这次测试无关),grep -c "^执行时段错误"结果为 0,没有任何Bad argument/Undefined function/崩溃堆栈。- 战斗结束后
quit干净退出,无残留错误。测试造成的data/{login,user}/f/fluffos.o存档漂移(fluffos战斗后的状 态变化)已用git checkout HEAD撤销,恢复到测试前的存档内容。
结论:战斗机制本身工作正常,没有发现程序 bug。 木人门槛依旧
是内容设计(维持第二轮结论不变),但这份档案的战斗系统现在已经用
一个真正可达、真正会打的敌对 NPC 完整验证过一次真实交手到收尾。
至此 hell 档案的注册、投胎、拜师、经济、战斗五大系统全部完成过
至少一轮真实的端到端验证,§10.7 深度功能测试可以标记为完整收尾。
AGENTS.md §8.3a variant fix (2026-08-27): feature/action.lpc::eval_function() and inherit/item/combined.lpc::destruct_me() wrongly private
Targeted follow-up from libs/revive's own deep-test pass (its NOTES.md
"§8.3a variant confirmed" section), which flagged that its sibling
revive/zjdyaryl/xuanjianlu lineage carries the same private
mixin-function demotion bug beyond command_hook, and specifically
named hell and zjmudhell as still carrying it unfixed. Confirmed
present here byte-identical to the revive shape:
feature/action.lpc::start_call_out()doescall_out("eval_function", delay, ...), buteval_functionwas declaredprivate.F_ACTIONis inherited intoinherit/char/char.lpc->clone/user/user.lpc(the player body), so this driver'sprivate->DECL_HIDDENdemotion on inherit silently no-ops everystart_call_out()-based delayed callback game-wide: kungfu temporary-condition effects (kungfu/special/{agile,hatred,power}.lpc), sleep/meditation wakeup (cmds/std/sleep.lpc,cmds/skill/jingzuo.lpc), room-cart arrival, combat's owncontinue_attack(adm/daemons/combatd.lpc), etc.inherit/item/combined.lpc::set_amount(0)doescall_out( "destruct_me", 0)to self-destruct an emptied stackable item, butdestruct_mewasprivate.COMBINED_ITEMis inherited byinherit/item/money.lpc,inherit/weapon/throwing.lpc,inherit/medicine/powder.lpcand severalclone/*items — every coin/thrown-weapon/medicine-powder stack reduced to zero would silently linger forever instead of self-destructing.
Fix (matching the established revive/§8.3a pattern exactly):
dropped private from both declarations, function bodies unchanged.
Verified live (native build-debug driver, port 40114, exact-PID
kill between reboots): before the fix, sleep in a sleep_room
(/d/guanwai/xiuxishi) printed "你往床上一躺,开始睡觉。不一会儿,
你就进入了梦乡。" and then genuinely never woke the character up (no
wakeup() message even after 6+ idle seconds) — a live-reproduced
instance of start_call_out()'s call_out("eval_function", ...)
silently failing. After the fix, the identical sleep sequence
correctly fired wakeup() within its 1-2s delay window ("你一觉醒
来,只觉精力充沛。该活动一下了。"). debug.log clean of any
执行时段错误/Bad argument both before and after (the bug fails
silently, it doesn't throw). Incidental data/newsd.o and
data/user/f/fluffos.o save drift from the test login reverted via
git checkout before committing.
destruct_me() not independently live-repro'd this session (would
require driving a coin/material stack down to exactly zero via item
commands) — fix rests on the identical fixed-in-place eval_function
mechanism and the established revive/demonangel precedent.
Locked sibling: 谁与争锋 / SYZF is hell4 (2026-09-05)
User identification: leftover archive 谁与争锋.7z (catalog slug swzf,
row 932) is hell4, a Doing/地狱 branded snapshot of this same family,
not a new unique game. The 7z is still header-encrypted. hell4 is the
game name, not the extract password (7z t -phell4 and related variants
fail). File size differs from this lib's hell.7z (9.0 MiB vs 5.4 MiB),
so it is not duplicate_of. When it opens, number it as 076-N.
深度功能测试(§10.7,2026-10-04)— negative range ends
scripts/lpc_fix_negative_ranges.py: 4 line(s) in 1 file(s) count a range from the end with < (x[a..-1] -> x[a..<1], x[-2..] -> x[<2..]; KB 06 §7.209). In this driver a negative constant end gave "" / ({ }) and a negative start the whole value, so each of these returned the wrong slice; the compile warning A negative constant as the second element of arr[x..y] is gone from the files that compile. Range lvalues (s[0..-1] = text, the prepend idiom) are left alone. A paired compile of the changed files at HEAD and in the working tree showed no new error.
深度功能测试(§10.7,2026-10-05)— 房间列出的物件缺档时房间照常加载
房间基类 inherit/room/room.lpc:make_inventory() 用 catch() 包住 new(file),做不出来就返回 0;reset() 的 case 1: 拿到 0 就跳过这一项(if (!objectp(ob[list[i]])) break;)。档案里没有的 NPC 或物品(或 create() 出错的物件)原先会让列出它的房间整个加载失败(Bad argument 1 to environment(),或对 0 的 call_other()),连带这个房间后面的区域;现在房间照常加载,只是少了那个物件,下次 reset() 再试(KB 05 §7.25;scripts/lpc_resilient_room.py、scripts/lpc_room_reset_guard.py)。
验证:探针(scripts/lpc_room_reset_probe.py:房间基类列出一个不存在的物件,再调用 reset())HEAD 单件 崩溃、多件 崩溃,工作树 单件 OK、多件 OK。
深度功能测试(§10.7,2026-10-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,新进程),无回退。
深度功能测试(§10.7,2026-10-07)— 编译警告整理
scripts/lpc_warnings.py hell --fix 加 scripts/lpc_fix_no_effect.py --apply,共改动 548 个 .lpc 和若干 .h。HEAD 与工作树分别加载(新进程):541 -> 541 通过,无回退;改过的头文件的 127 个包含者 126 -> 126 通过。
手工(与 zjmudhell、zjdyzj 等相同):28 处 Illegal to declare nosave function——include/globals.h 的 #define nosave nosave 让扫描工具认不出这个关键字,手工改成 protected;adm/daemons/natured.lpc 的空语句 lt[LT_MON];、adm/daemons/combatd.lpc 和 test.lpc 的空语句 your_temp["guarding"]; 删去。都不改变行为。
启动时警告 53 -> 0;新进程登录(新人物确认)正常。
- 2026-10-12:
adm/npc/obj/xiang.lpc、adm/npc/obj/xiang1.lpc、adm/npc/obj/xiang2.lpc写着int remove() { save(); },盖掉了feature/move.lpc的remove(string euid)——这些存盘箱子/柜子被销毁时不从携带者身上减负重、不清 handing(KB 06 §7.239 变体,nitan_ceshi/tianxiawuxue 同类)。改成varargs void remove(string euid) { save(); ::remove(euid); }。HEAD 与工作树各载入一次,regress 0(载不进的文件在 HEAD 就载不进)。
- 2026-10-12:
clone/misc/swmuding.lpc(神木王鼎)自己声明了一张mapping insects虫表,与继承的clone/misc/muding.lpc的insects同名;读表的是木鼎的代码,读到的是木鼎自己的表,神木王鼎的虫表从来没用上(Redeclaration of global variable 'insects')。改名sw_insects,create()里insects = sw_insects;交给木鼎(nitan170911、wxddym、zjdy 系同修)。HEAD 与工作树各载入一次,regress 0。
编译警告收尾(2026-10-13)
手工清零;改动的 6 个对象(含 clone/food/ganliang、d/guanwai/obj/wan、cmds/std/eat)在 HEAD 与工作树各载入一次,regress 0。
feature/food.lpc、feature/liquid.lpc的do_effect()是void,而重载它的干粮ganliang(三处)、d/guanwai/obj/wan.lpc、d/xiakedao/obj/pigpart.h返回int,eat/drink对only_do_effect物品用这个返回值做命令结果:基类改varargs int do_effect(object me),返回 1(同 yanhuangwuhun)。cmds/wiz/who1.lpc里一行孤立的分隔线字符串(WHT "———…" NOR;)不赋给任何东西,从不输出,删去(输出不变)。
- 2026-10-14:新驱动(FluffOS 970d9f09)报
Float value truncated to int(#1426)。1 个文件 3 处:赋值、初始化、return 改写成to_int(...)(值不变,只是写明截断)。改动的对象新进程各载入一次,无回退(scripts/lpc_fix_float_trunc.py,KB 04 §6.10)。
- 2026-10-14:1 个文件用了颜色宏(
HIW、NOR)却没有#include <ansi.h>(首个错误syntax error, unexpected L_STRING);开头补上(KB 04 §6.1、§6.3)。新进程比对 HEAD 与工作树:1 个对象,新增载入 1,回退 0。
负数伤害当作消耗(2026-10-15,KB 06 §7.241)
receive_damage("neili", -52)、receive_damage("qi", -12) 之类把 add() 的负数写进了 receive_damage():本库 feature/damage.lpc 对负数伤害报错(或归零),练功/运功时报 F_DAMAGE: 伤害值为负值 或消耗失效。已改为正数伤害,内力/精力类改为 add(type, -N)(scripts/lpc_fix_damage_calls.py):/kungfu/skill/duanyun-fu、/kungfu/skill/feifeng-whip。
转码吃掉的引号(2026-10-15,KB 03)
原档在右引号前有一个孤立的 GBK 前导字节,转 UTF-8 时连引号一起丢了(如 return name + HIM "发作身亡了;),字符串一直延续到后面,文件编译失败:/inherit/condition/damo。补回引号(scripts/lpc_fix_eaten_quote.py)。其中 /inherit/condition/damo.lpc 不能编译时,所有 damo_*(达摩)中毒状态都载入失败。
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 的身体,这一改动不改变行为。
技能名拼错(2026-10-15,KB 06 §7.249)
query_skill() 里的技能名拼错了,或用的是本库改名前的旧名;本库没有这个技能,调用永远得 0:门槛(< N 就拒绝)永远过不去,相关功夫或绝招学不了、用不了;内功互斥(> N 就拒绝)从不生效;公式里这一项一直是 0。经汉字名(提示文字或中文名词典)或纯拼写差异(_/-、少一个连字符、相邻字母颠倒)核对后,改为本库的技能名(scripts/lpc_fix_skill_typo.py):choushui-zhang→chousui-zhang(chousui-zhang);cuhixiao-jifa→chuixiao-jifa(xiaoao-jianghu);lenyue-shengong→lengyue-shengong(lengyue-shengong);matrial-cognize→martial-cognize(qiankun-danuoyi/nuoyi);taiji-shengon→taiji-shengong(taiji-shengong)。
技能名拼错:技能文件里拼错自己的名字(2026-10-15,KB 06 §7.249)
技能自己的文件(或它的绝招目录)里,query_skill() 读的是差一个字母的自己的名字,永远得 0:“基本功夫要高过本技能”之类的限制从不生效,按等级取招、计算伤害的那一项一直是 0。改为本技能的名字(scripts/lpc_fix_skill_typo.py 的 self 判据):shicheng-liulang→shicheng-liulong(shicheng-liulong);xuanyuan-arror→xuanyuan-arrow(xuanyuan-arrow)。
柔云步法「柔云纵」有时报错(2026-10-15,KB 06 §7.251)
rouyun-steps/zong 随机把人送到三个房间之一:精、精力已经扣了,“乘云而去了”也说了,送不过去时人留在战斗里并报错。第三个是巫师的测试房 /u/deaner/test1,库里没有;改为 /d/city/guangchang(hy、jym 等库原本就用这个)。
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,而不是得到拒绝。1 处(1 个文件)改为 dbase 路径查询 query("family/master_name"):有门派时值相同,没有时得 0;原有的判断照常生效(scripts/lpc_fix_family_index.py)。给映射赋值的写法未动。
昆仑气法「流」编译失败(2026-10-15)
从 xkx 系抄来的 kunlun-qifa/liu 引用 /kungfu/skill/eff_msg.h,本库没有这个头文件(只有这一个文件用它)。唯一用到的 eff_status_msg() 本库的 combatd 就有,改为 COMBAT_D->eff_status_msg(),去掉那行 include;现在能载入。
set_skill() skips a skill the lib has no file for (2026-10-18, KB 06 7.256)
set_skill(), map_skill() and prepare_skill() of feature/skill.lpc raised error("F_SKILL: No such skill (...)") on a name without a skill file, which aborted the calling NPC's create(): the NPC never loaded and the room that spawns it lost it. No object of this lib sets a missing skill today; The three now return: the skill is not granted or mapped and the object loads without it (the missing skill itself stays a content gap). (scripts/lpc_guard_set_skill.py)
NPCs that name a misspelled skill (2026-10-19, KB 06 7.258)
set_skill("kunlun-shnfa", ...) and map_skill("dodge", "shaolin-shnfa") spell a skill the lib does not have; the lib has the right one. Such an NPC used to die in create() with No such skill; since a missing skill is skipped it loads, but without that skill. Corrected from a reviewed table, 12 names in 9 files: changquana -> changquan (4), tiaji-jian -> taiji-jian (2), taiji-shenfong -> taiji-shengong (1), yan-fly -> yanfly (1), lingboweibu -> lingbo-weibu (1), jiahua-neigong -> jiaohua-neigong (1), zhoangnan-zhi -> zhongnan-zhi (1), jinggang-zhi -> jingang-zhi (1) (scripts/lpc_fix_skill_names.py).
query_autoload() 后面又追加了一个空桩(2026-10-19,KB 06 §7.266)
clone/misc/bandage.lpc、clone/special/jindouyun.lpc、clone/special/shunfenger.lpc 已经有真正的 string query_autoload()(返回绷带的名字或数量,配 autoload(string arg) 恢复),文件末尾却又追加了 int query_autoload() { return 1; },驱动报 Redeclaration of function 'query_autoload',整个物件载入不了。真正起作用的是字符串版本,删掉末尾那个追加的空桩。
标准整理轮(2026-10-19,scripts/toolkit_fix.sh)
本库在新驱动下重扫,机械修复:2 个函数补上 varargs(调用处少传参数)。修后与 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 文件。
补回丢失的标点(2026-10-19,KB 03 §4.6)
转换时丢掉的分号、逗号、引号或文件末尾的 },共 1 个文件,修前 HEAD 载入失败。别的库里同路径的完好副本只比这里少几个标点,按它补回(括号里是那个库):/d/baituo/obj/bowl.lpc(jhfy3)。修后与 HEAD 逐个对比载入:这 1 个物件全部载入,没有退步(scripts/lpc_restore_from_twin.py、lpc_fix_eaten_quote.py --comma、lpc_fix_eof_braces.py)。
从 work/ 里删掉 tar 的 PaxHeader/ 记录(2026-10-19,KB 02 §2.2)
压缩包的制作者把 tar 的 pax 扩展头记录(49 path = ...、20 ctime = ...,每个不超过 262 字节)当成文件打进了包里,放在 PaxHeader/ 目录(有的嵌套两层)。转换时 .c 结尾的被改名成 .lpc,在扫描里成了编译不过的“物件”。这些是元数据,不是 mudlib 内容:2 个文件从 work/ 删除(raw/ 里仍然有)。
x != "a" || x != "b" 和 x == "a" && x == "b":同一个值的比较链永远成立/永远不成立(2026-10-20,KB 06 §7.282)
if (arg != "wan" || arg != "丸") return notify_fail(...) 对任何 arg 都为真,dir == "south" && dir == "north" 永远为假:条件下面的守卫要么永远拦、要么永远不拦。作者要的是“既不是 A 也不是 B”(&&)或“是 A 或 B”(||)。!= 链的 || 改成 &&(仅当条件下面是 return 的拒绝/守卫),== 链的 && 改成 ||(scripts/lpc_fix_cmp_chain.py)。改动:/d/mingjiao/shanmen.lpc(1 处)。
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 处)。改动:/kungfu/class/quanzhen/wang.lpc(1 处)。
登录密码超过 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)。
目录读出后的后缀截取宽度(2026-10-20,KB 06 §7.296)
.c 改名成 .lpc 之后,get_dir("*.lpc") 读出的文件名还按两个字符截取($1[0..<3]):baguadao.lpc 变成 baguadao.l,用它拼出的路径加载不到对象(故事、战场、事件、帮助、自造物品数据、召唤列表等)。改成 [0..<5](scripts/lpc_fix_getdir_strip.py)。改动:/adm/daemons/storyd.lpc(1 处)、/adm/single/importer.lpc(1 处)。
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 处)。
NPC 的 chat() 在 chat_msg 为空数组时下标越界(2026-10-21,KB 06 §7.334)
NPC 基类的 chat() 是 if (arrayp(msg = query(...))) { if (random(100) < chance) { rnd = random(sizeof(msg)); if (stringp(msg[rnd])) ...,不检查列表是否为空。本库现有的 NPC 文件里没有字面写成空 chat_msg 的(扫描只认 set("chat_msg", ({ })));守卫挡的是运行时才为空的列表和以后新增的 NPC。在 random(100) < chance 前面加 sizeof(msg) &&(scripts/lpc_fix_chat_empty.py;if (random(100) > chance) return 0; 的写法是 !sizeof(msg) ||)。改动:/inherit/char/npc.lpc(共 1 个文件)。
注册到不存在函数的 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.,同一个动词的其他处理函数不再尝试(不是最新的一条就悄悄跳过)。删除了 13 条注册(6 个文件,scripts/lpc_fix_dead_add_action.py),动词留给别的处理函数:/adm/npc/laopu.lpc(add_force、add_skill、buy_vip、do_vip等)、/adm/npc/referee.lpc(do_halt)、/d/beijing/hg_w.lpc(do_body)、/d/room/roomnpc/shouwei.lpc(buy_vip、do_vip、list_vip)、/d/tulong/yitian/npc/obj/ling2.lpc(do_du)、/inherit/misc/fboard.lpc(do_list)。最多的函数名:buy_vip 2 处、do_vip 2 处、list_vip 2 处、do_halt 2 处、add_force 1 处。
对象路径里的 ..: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")。
调用了、但这个库自己的守护进程里没有的函数(2026-10-22,KB 06 §7.354)
MACRO->函数() 调用的函数在这个库的守护进程里不存在:call_other() 对不存在的函数不报错、只返回 0,所以这些功能(时间显示、昼夜事件、名字检查、价格文字……)一直没起作用。同一血统另一个库的同名守护进程里有这些函数,原文照抄到本库守护进程末尾(scripts/lpc_port_function.py;调用处传的参数个数、函数体用到的函数 / 全局变量 / 宏 / 字符串键都在本库里有,已核对;守护进程在 HEAD 和工作区都能加载,每个函数用固定参数各调用一次:HEAD 返回 0,现在返回正常的值):/adm/daemons/chinesed.lpc ← hhsj:find_skill()(1 处调用)。
汉字按字节切片的老写法没有换成按字符:改法名 "澄" + name[2..3]、辈分判断 name[0..1] == "澄" 等 15 处(2026-10-22,KB 06 §7.360)
原档按字节算字符串区间(一个汉字 2 字节):name[2..3] 是名字的第二个字,name[0..1] == "澄" 问名字是不是以「澄」开头。转成 UTF-8 之后,这个驱动的区间和 strlen() 都按字符算(strlen("澄观") 是 2,"澄观"[0..1] 是两个字),老算术原样留着、意思全变:拜入少林 / 武当 / 峨嵋等派的玩家被改成错误的法名(二字名 张三 变成一个字的 澄,更长的名字取到第三个字);各派掌门的辈分判断(name[0..1] == "澄")永远不成立;NPC 的称呼和提示里取到两个字而不是一个字。
本库 15 处(10 个文件):拼名字的赋值 8 处、与汉字常量比较 6 处、to_chinese()[..] 1 处。例:name[0..1] → name[0..0](/kungfu/class/emei/tobebonze.h:40);name[2..3] → name[1..1](/kungfu/class/shaolin/cheng.h:164);chk[0..1] == "你" → chk[0..0] == "你"(/adm/npc/ganjiang.lpc:542)。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) > 12)) {(/adm/npc/luban.lpc:1770)。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)。本库 channeld 同盟 / 门派标题 1 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。
血条 / 表情标题按字节算显示宽度(2026-10-23,KB 06 §7.365)
老档把汉字当两字节:bar_string[0..(val * N / max) * 2 - 1] 把「格数」换成字节下标,半格血条在本驱动(按字符算区间)上会整条画满;巫师表情 edemote 的 repeat_string("─", 13 - (strlen(emotion) / 2)) 也会少减汉字宽度。scripts/lpc_fix_display_pad.py:去掉 CJK 血条 / 空白条上的 * 2(jings/qis 赋值和 blank_string3[0..(23-a)] 的 23→11 一并改),表情标题去掉 / 2;ASCII 空格的 none_string / empty_string 仍保留 * 2(一格两个空格)。本库 2 处(1 个文件)。证明(lpcc_eval.py hhsj):tribar_graph(6,9,12) 在 HEAD 画出整条 12 个■,改后为 6 个■+3 个□;麻将 strlen(tempB)/2 是两字符牌码,未改。
中文名 / 验证码仍按 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。
yuanwai 孤儿 call_out announce_success(2026-10-27,KB 06 §7.349 Also)
d/changan/npc/yuanwai.lpc(及 aoxiangtianji 的 d/city 副本)在 check_daughter 里 call_out("announce_success", …),但本文件从未定义该函数;同系也无实现。到点会 *Undefined function*。cry_daughter 已完成认亲与赠书,删除这对 remove_call_out/call_out。证明:扫描 HIT call_out→announce_success 且无定义;改后残渣 0。
深度功能测试(2026-10-27,§6.25 zhongling tell_object 引号错位)
d/wanjiegu/npc/zhongling(及同路径副本)的 tell_object("who, 钟灵脱下一双绣花鞋。\n") 把对象参数写进了字符串;改为 tell_object(who, "…")。证明:原文错位;改后加载,语料残渣 0。
深度功能测试(2026-10-27,§6.10 未知 pragma save_binary/optimize)
删除本库中 FluffOS 不认的 #pragma save_binary / #pragma optimize… 行。