Lima Mudlib

✅ 可玩

Lima

lima

🔑 fluffos / Mud@2026 更新 4e295b0 2026-09-12 源码 下载 ZIP 上游 limalib/lima 落后 1 提交

▶ 开始游玩 · Play Now

LIMA 社区仍在维护的参考 mudlib(源码: <https://github.com/limalib/lima>,官网 <https://www.limamudlib.dev/>)。这不是一款武侠/仙侠游戏——和本项目收录的其它中文 mudlib 不是同一个宗谱,是一个独立的、英文的、面向开发者的现代 LPC 框架,收录进本项目是作为 "当代 FluffOS mudlib 长什么样"的参照样本。

English

The maintained LIMA mudlib (limalib/lima, limamudlib.dev) -- an English-language, developer-facing framework built to demonstrate what a modern LPC mudlib looks like, quite unlike the classic Chinese wuxia lineages that make up most of this collection. Rather than registering one verb per add_action, Lima understands full natural-language sentences ('take the red potion from the box'), secures files and commands through a capability-based system of privileges/domains/protections instead of the traditional uid/root model, and gives every wizard a Unix-like shell (variables, pipes, globbing) rather than a fixed command table. New characters begin in the Grand Hall, a wizards' meeting room with polished floorboards and rough-hewn beams, flanked by a sulfurous northwest passage, a passage to the south that smells like something recently died, and an incongruous elevator door to the west; a glowing portal leads to the separate mortal starting area. Bundled demo content includes a nine-room 'Sandy Beach' pirate treasure-hunting puzzle (explicitly marked by its own author as not meant for a real, live mud) and optional contributed modules for bulletin boards, marriage, and in-room object creation. New characters are granted wizard powers automatically (AUTO_WIZ), the upstream project's own default for a framework meant to be explored and extended, not played as a finished game.

README

github.com/fluffos/lima 已于 2024-10-08 归档,不再是活跃上游。本馆按 submodule-patch 跟踪 limalib/limawork/ 是该仓库的 submodule(mudlib 根目录是 work/lib,上游保持 .c),本馆 FluffOS 兼容在 patches/,管理员播种在 overlay/。真源码 bug 往 limalib/lima 提(本馆已合入的 #49 / #50 / #51 在上游 2026-09-03 HEAD ffed9c588ee5)。

架构说明

Lima 在几乎每个层面都和本项目里的经典 LPMud 系 mudlib 不同:

详见 NOTES.md,里面有完整的转换记录、发现并修复的驱动兼容性 bug、 以及为什么这个 lib 需要一个专门编译的驱动。

特殊要求:需要专用驱动

这个 lib 不能用本项目其它 ~240 个 lib 共用的默认驱动 (~/src/fluffos/build-debug)启动——Lima 自带的 secure/check_config.c 会在启动时检查驱动是否按它要求的编译期开关 (NO_LIGHT/NO_ADD_ACTION/NO_WIZARDS 已定义,OLD_ED/ PACKAGE_UIDS 未定义)编译,不满足就直接报错中止,而本项目的共享 驱动是按相反的开关编译的(其余所有 lib 都需要那一套)。

已经在 ~/src/fluffos-lima~/src/fluffos 的一个独立 git worktree, 同一份源码不同的编译配置)按 Lima 的要求单独编译出了一份驱动,运行 时要用:

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

(如果 ~/src/fluffos-lima 不存在,NOTES.md 里有完整的重建步骤, 一次性编译大约 5-10 分钟。)

游戏端口:40212。原生(native)驱动已验证。站点现在按 lib 覆盖 WASM 驱动(scripts/custom_drivers/lima_swmud/,与 swmud 共用), 浏览器试玩已走通注册→选种族→进入 Grand Hall,wasm_statusplayable。详见 NOTES.md「站点基础设施缺口已补上」。

本地运行

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

连接后按提示注册(英文 id + 密码 + 性别/邮箱/真实姓名等基本信息), 在用户菜单里用 c 创建角色、选择种族,s 选中、p 进入游戏。核心 指令:lookscore(状态面板)、inventorywhoquit

管理员账号 / Admin account

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

NOTES · 移植与修复记录

lima — Lima Mudlib

来源:活跃上游是 limalib/lima(HEAD ffed9c588ee5,2026-09-03; 官网 <https://www.limamudlib.dev/>)。本馆可玩树最初从已归档的 fluffos/lima 克隆(dbcef2a Update fluffos/lima to 1.1a2 (#33), 2026-08-24)。编号 164,端口 40212。状态:done(干净启动,真实注册 流程 + 角色创建 + look/score/inventory/who/quit 全部验证可用; 管理员账号 fluffos 已播种并验证 update/admtool 等高权限指令)。 hostingsubmodule-patch。leftover 684:work/ 已切成 limalib/lima submodule(pin ffed9c588ee5),config.fluffos 的 mudlib directory 指向 work/lib

leftover 684:lima work/ 切到 limalib/lima submodule

按 leftover 682/683:非 fluffos 活跃上游保持他们的 .c,本馆兼容进 patches/work/ 现在是 limalib/lima 的 gitlink,不再是本馆 .lpc 格式化树。catalog-only 补丁:

站点 zip 在 staging 上 apply patches + rsync overlay,所以下载仍是 可玩、可复现的源码树。autodoc.c 的行内 END 标记仍不编译,http_d 未 preload,不影响游玩。

leftover 683:归档的 fluffos/lima 不是 hosting 目标

fluffos/lima 2024-10-08 已 archived。按 leftover 682 的规则,归档 = 不再活跃,不能当 fluffos-upstream。活跃上游是同一 LIMA 社区的 limalib/lima(本馆 PR #49/#50/#51 已于 2026-09-03 合入)。meta.json 改为 hosting: submodule-patch,pin ffed9c588ee5。leftover 684 已把 work/ 切成该 submodule(见上一节)。

这个 lib 的架构,写给不熟悉 Lima 的读者

Lima 不是本项目里常见的"侠客行/金庸群侠传"系语系(LPMud 经典宗谱), 而是 FluffOS 驱动项目自己维护的官方参考 mudlib(<https://limalib.dev>), 英文,面向开发者/巫师的框架式设计,和本项目收录的绝大多数中文武侠 mudlib 在几乎每个层面上都不同:

§7.46 的后续:LIMA 系驱动编译选项冲突,这次真的解决了

AGENTS.md §7.46 早先记录过一个结论:"基于 LIMA 代码库的 mudlib 需要 本项目共享驱动没有的编译期开关(NO_LIGHT/NO_ADD_ACTION/ NO_WIZARDS/undef OLD_ED/undef PACKAGE_UIDS),不在源码层面可修, 需要一个单独编译的驱动 —— 当时判定为 out of scope"(案例:sgzmudsgz, 一个基于 LIMA 代码库的三国志 MUD)。这次直接拿到了 LIMA 本尊,所以把 这件事真正做掉了:

重要libs/lima/ 不能用 ~/src/fluffos/build-debug(本项目其余 ~240 个 lib 共用的默认驱动)启动——secure/check_config.c 会在 simul_efun 编译时因为上述六项全部不满足而报错并中止启动。必须用 ~/src/fluffos-lima/build-debug/src/driver。这个 worktree 是本 session 新建的,不在 git 版本控制内~/src/,不是 libs/lima/ 下), 如果这台机器/这个 checkout 丢失了要重新按上面步骤建一次——大概 5-10 分钟的一次性编译,之后复用。

WASM 状态当时标为 partial (native only):要让这个 lib 在浏览器里跑, 还需要在 emcmake cmake --preset wasm 的基础上叠加同样的 local_options/PACKAGE_UIDS=OFF 改动,构建一个专用的 wasm 驱动—— 留作未来工作,这次 session 的任务范围(见协调者的原始指令)没有要求 WASM 通道。(2026-09-01 更新:这个专用 wasm 驱动后来真的建出来了、 且验证可用——见下方「wasm_status 审计」一节。partial 本身也不是这个 项目 wasm_status 枚举里的合法值之一,scripts/gen_site_index.pyEXCLUDE_STATUSES 把它当"deliberately deprioritized, e.g. ds386"处理 而不是"boots but WASM未验证"——当时这样写等于把这个 lib 从站点彻底 排除,而不是标成"限制",这正是本次审计要修的那类 wasm_status 误标。)

wasm_status 审计(2026-09-01):专用 WASM 驱动建成、但站点基础设施还接不上

之前 meta.jsonwasm_status 一直留空——本节记录 2026-09-01 那次 批量审计([[project_wasm_status_audit]])对这个 lib 的完整调查过程和 最终结论:noboot(不是 playable,原因见下)。

专用 WASM 驱动:编译成功,mudlib 本身完全可玩

复用已有的 ~/src/fluffos-lima(git worktree,src/local_options 已经 按上面的六项要求改好):

cd ~/src/fluffos-lima
source ~/src/emsdk/emsdk_env.sh
cmake --preset native-tools && cmake --build --preset native-tools -- -j8
emcmake cmake --preset wasm -DPACKAGE_UIDS=OFF
cmake --build --preset wasm -- -j8

/opt/wasm-deps 下的 ICU/zlib 已经是全项目共享、编译好的,不需要 重新跑 tools/wasm/build-deps.sh。)一次性编译成功,产出 ~/src/fluffos-lima/build-wasm/src/{fluffos.js,fluffos.wasm}

第一次用 scripts/wasm_client.js 起跑立即命中和 ds386/dsII/dsIII 同一类"sockets 包缺失导致 simul_efun 编译失败"的 bug(AGENTS.md §1.3(c) 那一类,这次是首次在 lima 自身代码里发现,而不是三国/西游同人 mudlib 里的变体):secure/simul_efun/misc.lpcdump_socket_status() 无条件调用 socket_status()——这个 efun 只在编译了 sockets 包的 驱动上存在(WASM 构建默认不带 sockets 包,浏览器沙箱里没有真实 socket 的语义),所以这不只是运行时缺失,而是编译期就报 "Undefined function socket_status",导致整个 secure/simul_efun 编译失败(*No program in object '/secure/simul_efun/misc'!), 驱动直接拒绝启动("The simul_efun ... and master ... objects must be loadable")。修复(#ifdef __PACKAGE_SOCKETS__ 包一层,没有这个包时 退化成返回空字符串,和 ds386 已有的同类修复手法一致):

string dump_socket_status()
{
#ifdef __PACKAGE_SOCKETS__
    ... (原有实现,逐行不变) ...
#else
    return "";
#endif
}

修复后用 wasm_client.js 完整跑通一次真实会话:fluffos/Mud@2026 登录 → 用户菜单等到 auto-login 10 秒倒计时自动进入游戏(也可以直接 输入 p 跳过倒计时)→ 落地 Grand Hall → score 显示完整的属性/ 经验/负重面板 → quit 干净退出("You have left Lima Mud."),全程 driver_stdout.log 无一条运行期错误。这套 mudlib 内容本身在专用 WASM 驱动上是完全可玩的——之前 README 写的"WASM 通道未构建"这句话 现在已经不成立了,专用驱动确实建出来了且验证通过。

原生驱动(~/src/fluffos-lima/build-debug/src/driver)用同样的 fluffos/Mud@2026 账号复测,无回归。

但站点实际部署用的是唯一一份共享驱动,这个专用驱动接不进去

问题出在这个项目的站点打包管线,不在 lima 自己身上: scripts/write_play_page.sh 把每个 lib 的 play.html 写进站点时, 里面的驱动脚本引用是写死的相对路径 ../_driver/fluffos.js——_driver/ 是整个站点唯一一份共享的 WASM 驱动产物(来自 ~/src/fluffos/build-wasm),所有 ~240 个 lib 共用同一份二进制, 没有任何"这个 lib 用另一份驱动"的每-lib 覆盖机制(build_site.sh/ write_play_page.sh 通读一遍,找不到任何 per-lib driver 路径参数)。

secure/check_config.lpc 的六项检查(NO_LIGHT/NO_ADD_ACTION/ NO_WIZARDS/OLD_ED/PACKAGE_UIDS)在任何驱动上、在 create() 里都会无条件跑一遍,不分 native 还是 WASM——用共享站点驱动(没有按 lima 的要求编译)跑 lima,这个检查一定会 error() 掉,跟本地这次 用专用驱动之前遇到的、AGENTS.md §7.46 记录的"驱动编译选项冲突"是 同一个错误。也就是说:即使这次把专用 WASM 驱动建出来了,部署到 mudlibs.fluffos.info 上的那份 lima 实际上还是会用共享驱动去启动, 一样会在 simul_efun 编译期报错中止——wasm_status: playable 会是 一句谎言,不代表访客点开这个 lib 的页面真的能玩。

结论:wasm_status 设为 noboot

按审计任务给出的定义("noboot: 即使 native 能跑,WASM 下也跑不 起来")——这里的"WASM"应该理解成"这个项目实际部署的 WASM 环境",也就是 共享驱动,而不是"技术上存在某种 WASM 驱动配置能跑"。专用驱动的存在 证明了 mudlib 内容层不是问题,问题完全在站点基础设施的"一份驱动打包 所有 lib"这个假设上,这已经超出本次审计("修正个别 lib 的 wasm_status 字段")的范围,属于一次单独的站点管线改造工作(给 write_play_page.sh/build_site.sh 加一个 per-lib 驱动目录覆盖 参数,再单独为 lima 归档 ~/src/fluffos-lima/build-wasm 的产物)。 把这个专用驱动的完整构建步骤记在上面,方便未来那次改造直接复用, 不用重新摸索 check_config.lpc 的六项要求或重新踩一遍 __PACKAGE_SOCKETS__ 这个坑。

secure/simul_efun/misc.lpc 的这处修复本身不依赖站点基础设施,已经 提交进 libs/lima/work/——不管未来站点管线怎么改,这个修复都是 必需的前置条件,先做掉不亏。

站点基础设施缺口已补上(2026-09-02/03):wasm_status 翻正为 playable

上一节末尾说的"未来那次改造"这次做掉了:write_play_page.sh 新增 一个可选的第 5 个参数(自定义驱动目录),给出时把该目录下的 fluffos.js/fluffos.wasm 拷进这个 lib 自己的站点输出目录, play.html 里的驱动脚本引用也相应改成本地路径而非共享的 ../_driver/telnet.js/vendor/xterm 这些和驱动编译选项无关的 文件仍然共享)。build_site.sh 新增一个 custom_driver_dir_for() 查找表,lima/swmud/spacemud 三个 slug 映射到 scripts/custom_drivers/lima_swmud/——本节上面记录的那份专用驱动 产物(~/src/fluffos-lima/build-wasm/src/{fluffos.js,fluffos.wasm}, 2026-08-24 的 fluffos/fluffos@721878c 构建)直接提交进了这个目录, 不需要在 CI 里重新编译(CI 没有装 emsdk,见 AGENTS.md §1.6)。

本地用 pack_lib_zip.sh + write_play_page.sh <slug> ... <custom_dir> 搭了一个范围内(只有这两个 lib)的测试站点验证:fluffos.js/ fluffos.wasm 正确落地在 lib 自己的输出目录,play.html 引用也正确 指向本地而非 ../_driver/。用 Playwright 通过真实的 #cmd 输入框 走完整个流程——注册、性别/种族选择、创建角色、s+p 进入游戏—— 落地 Grand Hall,look 正常显示房间描述,和本节前面用 wasm_client.js 跑通的那次结果完全一致,控制台无 JS 报错。

meta.jsonwasm_statusnoboot 改为 playable。见 libs/swmud/NOTES.md 对应小节(同一份驱动,独立验证)。

转换步骤(对照 AGENTS.md §2/§2.3)

1. 克隆到 scratch 目录,lib/ 就是 mudlib 根(README 自带的 mudlib directory : ./lib);driver/(fluffos 子模块)、 resources/build.sh 等构建脚手架按约定忽略,只取 lib/。 2. 编码:整个仓库 1969 个文件里只有 2 个非 UTF-8——WWW/lima.jpg (二进制图片,正常)、help/wizard/coding/parser(一处 Latin-1 版权符号 ©iconv -f latin-1 -t utf-8 修复)。其余全部原生 ASCII/UTF-8,符合"最新 fluffos 兼容的现代仓库"预期,不需要 GB18030/BIG5 转换。 3. .c.lpcscripts/convert_lib.sh(用 UTF-8 作为"源编码" 跑一遍,等价于跳过转码、只做改名 + 引用修复),1095 个 .c 文件 全部重命名,118 处字面量 .c" 引用自动修复,0 处遗留。 - 发现一处 §4.2 条目 5("扩展名缺失文件 + 同名 .c 备份")的实例: secure/daemons/finger_d(无扩展名)与 finger_d.lpc(原 finger_d.c)内容不同。git log 确认 finger_d.c 是最近一次 commit(Update fluffos/lima to 1.1a2 #33)改过的版本,无扩展名 的那份自 #28 之后再没被碰过——是过时内容,已删除。 - static -> nosave 批量替换踩了 §4.3 描述的"字符串字面量误伤": domains/std/lima/workroom_ob.lpc 一句房间描述文本里恰好出现了 单词 static("a burst of static darts across your screen"), 被误替换成 nosave,已手动改回。include/global.h#ifndef __SENSIBLE_MODIFIERS__ #define nosave static #define protected static #endif 的兼容 shim(§4.3 第二类碰撞)也被误伤成 #define nosave nosave,同样改回原文——不过这个 shim 本来就在 #ifndef __SENSIBLE_MODIFIERS__ 保护下,本项目驱动始终定义 __SENSIBLE_MODIFIERS__,这段代码从未真正执行,改不改都不影响 行为,纯粹是为了保持源码忠实。

编译期发现的真实 bug(而非内容/示例缺口)

以下几处是驱动兼容性/程序错误,符合本项目"只修程序 bug,不改 内容设计"的范围,已修复:

1. .c.lpc 改名的连锁反应:命令查找机制本身就没跟上扩展名变长 (AGENTS.md §4.2 第4类"固定宽度切片而非扩展名操作",这次是同一类 bug 在上游自己的 .c-命名树里原本"恰好正确",被本项目的重命名 直接触发)。secure/daemons/cmd_d.lpccache_dir()get_dir(dir+"?*.lpc") 拿到文件名后用 $1[0..<3] 砍掉扩展名—— 这个切片宽度是为两个字符.c 算的(<3 在这个驱动的区间 语法里表示"从末尾数第 3 个字符(含)到开头",对 5 字节的 foo.c 算出 foo),改名后文件变成 4 字节的 .lpc,同一个 <3 切出 score.l 这种带垃圾尾巴的"命令名",导致几乎所有裸词形式的 巫师/玩家命令全部失效——scoreinventory 等在 shell 里输入 会报 I don't know the verb 'score',只有写全路径 /cmds/player/score 才能跑(score.lpc 本身完全正常,纯粹是 路径匹配层面的缓存 key 算错了)。这是这次转换里影响面最大的一个 bug——不修的话整个游戏对话式命令行基本不可用。同一切片模式在 cmd_d.lpc 另一处(smart_arg_parsing 里按绝对路径匹配后取 cmd_name)、daemons/spell_d.lpc(重建法术目录缓存)、 daemons/quest_d.lpc(显式 if (base[<2..]==".lpc") 判断之后却用 两字节宽度去砍)里各出现一次,一并改成 <5(对应 4 字节的 .lpc)。已用真实驱动重新启动、注册、score/inventory/update 等裸词命令验证全部恢复正常。全仓库还有 27 处同形态的 [0..<3] 切片,逐一读取上下文后确认其余都是无关的字符串截断(去掉末尾逗号、 "\n\n""::" 等),或是针对 .oSAVE_EXTENSION,仍是 2 字节, 不受影响)——只有以上 4 处真的和 .c.lpc 改名相关。 不提交上游:这是本项目自己 .c.lpc 改名操作触发的问题, 上游 fluffos/lima/limalib/lima 原生文件名仍是两字节的 .c[0..<3] 在那里本来就是对的——这是本项目的转换产物,不是 lima 自己源码里的 bug,不属于这次 upstream PR 审计范围(2026-08-31)。 2. set_droppable() 参数类型声明过窄std/modules/m_gettable.lpc 自己的文档注释写"传函数或字符串等效于调用 set_dropmsg()",函数体 也确实用 functionp(g) || stringp(g) 判断,但签名却声明成 void set_droppable(int g)——这个驱动的静态类型检查因此拒绝 domains/std/lima/directory.lpc/workroom_ob.lpc(后者正是新巫师 自己的 workroom)里传字符串自定义"拿不下来"提示语的调用。参数类型 改成 mixed g,和函数体实际行为、文档注释保持一致。 已提交上游fluffos/lima 已于 2024-10-08 被官方归档只读gh pr create 直接报 GraphQL 错误"Repository was archived so is read-only"),无法开 PR。经核实,同一 LIMA 社区(同一 Discord 频道 #LIMA、同名品牌"limamudlib.dev")已迁移到活跃维护的 limalib/lima(非 fork 关系但代码血缘一致,git clone 核对确认 m_gettable.c/m_exit.c/usermenu.c 三处逐字节相同,同一 bug 原样存在),已改为向 limalib/lima 提交: limalib/lima#49。 3. private 跨文件继承调用(AGENTS.md §7.48 标准案例): std/modules/m_exit.lpceval_dest() 声明为 private,却被 继承它的 std/modules/m_exit_obj.lpc 直接调用——这个驱动对 private 的强制比老 MudOS 严格(继承链内也不能跨文件调),改成 protected(比 private 宽松,不会引入新 bug,只会修好已经存在的 非法调用错误)。 已提交上游:同上,fluffos/lima 已归档,改为 limalib/lima#50。 4. 含内联注释的宏参数展开异常daemons/spell_d.lpcENSURE(spell_name /* 注释 */) 这种"宏参数里带 C 风格块注释"的写法 触发这个驱动预处理器的一个真实 bug——ENSURE 宏没有正常展开,报 Undefined function ENSURE 后级联出语法错误,导致 daemons/spell_d.lpc 本身以及依赖它的 6 个法术文件全部编译失败 (fireball/magic_arrow/unlock/test/ale 及 stock-mage 分支)。 已构造最小复现(两行 LPC:ENSURE(x /* c */);)确认与具体文件内容 无关,是宏参数解析器本身在"参数里含 /* */"时的通用问题——不打算在 本项目范围内修驱动本身(那是 fluffos/fluffos 的事,需要走 PR), 采用等价、保留原意的写法规避:把注释挪到宏调用外面ENSURE(spell_name); /* 注释 */),两处均已修复并验证。 不属于本次 lima queue 审计范围:这是 fluffos/fluffos 驱动本身的 bug,不是 fluffos/lima/limalib/lima 源码的 bug—— 本次任务(2026-08-31)只审计 lima 的 mudlib 源码是否需要提 PR, 驱动仓库层面的 PR 不在这次的范围内,未提交。 5. 含"开括号后紧跟内容"的 heredoc(@TAG content...)在这个驱动的 词法分析器里同样有真实问题std/race/troll.lpc@LONG Trolls are...)和 WWW/cgi/autodoc.lpc(7 处 @END<title>...)在开始标记同一行紧跟正文时报 End of file in text block——已用两行最小复现确认(@LONG hi\nthis is\na test\nLONG; 能编译,把首行改成 @LONG hi 同一行接内容就不能)。 同样倾向于判定为驱动词法分析器的真实 bug(不在本项目范围内修驱动, fluffos/fluffos 需要走 PR),mudlib 侧用等价、保留原文内容的写法 规避:把开始标记单独放一行,正文从下一行开始。troll.lpc 已完全 修好(唯一一处),autodoc.lpc 的 7 处开始标记都修了,但该文件的 HTML 内容里结束标记本身也不是顶格(比如 <UL> END +END 前面还有真实 HTML 内容),而这个驱动的 heredoc 结束标记 必须是整行的最前面——这是另一类、更深的方言差异(老式 LPC 允许 结束标记出现在缩进/行内任意位置,这个驱动不允许),不是简单挪一行 能解决的,autodoc.lpc 因此仍然编译失败。鉴于它只是一个默认未启用 (http_dpreload 里被注释掉)的巫师专用 CGI 文档生成工具, 不影响核心游玩,这里记录下来但不再深入修——留给以后需要真正用到 web 文档生成功能时再处理。 不属于本次 lima queue 审计范围:同上一条,这是 fluffos/fluffos 驱动词法分析器本身的 bug,不是 lima 源码的 bug,本次审计 (2026-08-31)未提交驱动仓库层面的 PR。 6. 赋值/比较符打错obj/usermenu/usermenu.lpcconfirm_decision()——if (dec == "yes" || dec = "y"),第二个条件 是赋值不是比较,导致这个函数永远返回真,无视用户实际输入的 "确认删除角色"对话框形同虚设(remove_char 流程里的 yes/no 确认, 不管输入什么都会被当作"是")。改成 ==已提交上游:同上两条,fluffos/lima 已归档,改为 limalib/lima#51

§2.2 On-sight checklist 结论

管理员账号播种

Lima 自己的安全模型是"能力(capability)+ 领域(domain)"式的,没有 本项目其它 lib 常见的"adm/etc/wizlist"或"(admin) 状态字符串", 而是 /data/secure/access.oSECURE_D 的存档文件, ACCESS_SAVE="/data/secure/access")里的 wizardsdomains["admin"] 两个 mapping。上游仓库自带的原始档案是一个"全新 安装、什么人都没有"的空白状态wizards ([])domains["admin"] ([]))——这本来就是设计使然:secure/user/sw_body.lpcsw_body_handle_new_logon() 里有一段"没有任何 admin 时,把第一个创建 角色的人自动提升为 admin"的引导逻辑(自举机制),正常情况下靠"第一个 真人巫师创建角色"就能完成播种,不需要额外操作。

但本项目的标准约定是固定的 fluffos/Mud@2026 账号,而不是"谁先手快 谁当家"——为了不依赖"谁第一个连上来"这种时序,直接编辑 data/secure/access.o(纯文本的 save_object() 格式,逐行 变量名 值 ),把 wizards 加上 "fluffos":1,把 domains["admin"] 加上 "fluffos":2(2 = 领域领主/lord,和 add_domain_member(domain, member, lord) 的语义一致)。这样一来, fluffos 一注册就直接是 admin,同时因为 domains["admin"] 已经非空, "自动提升第一个人"的引导逻辑不会再对后续任何测试账号触发(已用 traveler/finaltest 两个测试角色验证:它们注册后只拿到普通 AUTO_WIZ 赠送的 Wizard 权限,who 里 Role 显示 Wizard,不是 Admin——引导逻辑确实只认第一次)。data/secure/access_backup.osave_data() 顺带写的备份文件,启动时不读取)同步更新以保持一致, 测试期间产生的其它账号相关残留(traveler/finaltest 的存档、 data/referralsdata/secure/LOGdata/daemons/last_login.o)已 清理,只留 fluffos 一个种子账号。

验证:fluffos 登录后 who 显示 Role: Adminupdate /std/race/human(读+写都要过 ACL 的规范检验)和 admtool (进入管理菜单,能看到 1 - priv 1 选项)均成功,说明播种的不只是 "看起来像 admin"的展示状态,写权限确实生效。

已知但未修的内容/示例缺口(按项目惯例:不是程序 bug 就不动)

编译扫描(lpcc --batch,1095 个 .lpc 文件)在上述 bug 修复后还剩 38 个失败,逐一读取错误信息确认全部是内容/示例本身的缺口,不是 驱动兼容性问题:

定义完成的验证记录

scripts/mudclient.py 通过真实驱动完整走过三轮独立账号 (questorwanderertraveler,以及最终的 fluffos/finaltest): 注册(id/密码/性别/邮箱/真实姓名/主页/推荐来源全部走完)→ 用户菜单 c 创建角色 → 种族选择(human/elf 两种都测过)→ s 选择角色 → p 进入游戏 → 落地在 Grand Hall(Lima Bean 巫师聚会场所,游戏内自带的 "新手/巫师起始房间",因为 AUTO_WIZ 的关系每个新角色都从这里开始)→ look(房间描述正确重复)→ score(ASCII-art 状态面板,含种族对应的 六维属性、经验、卡玛值)→ inventory("You are empty handed.")→ who(正确列出在线角色和权限等级)→ quit(正常退出, [announce] 频道正确广播离线消息,回到用户菜单,debug.log 全程 无报错)。管理员账号额外验证 update/admtool。整个流程干净、无 崩溃、无静默失败。

附录(2026-08-26):limalib/lima("modernized LIMA" fork)调查结论 —— 负面结果,未新建 lib

外部研究提到一个 GitHub 仓库 limalib/lima(<https://github.com/limalib/lima>, 自称 "Updated, maintained, modernized LIMA mudlib updated to run latest FluffOS driver. Kept in the original LIMA spirit.",官网 limamudlib.dev,文档 docs.limamudlib.dev,HEAD eb25dc6,2025-10-27), 怀疑这个"现代化"分支是否已经从根本上摆脱了 §7.46 记录的驱动编译期开关 冲突(本条目上文已经用的那五项:NO_LIGHT/NO_ADD_ACTION/NO_WIZARDS/ undef OLD_ED/undef PACKAGE_UIDS)。本次任务专门验证了这一点—— 结论:没有,问题原样保留,limalib/limalibs/lima 用的 fluffos/lima 一样,需要同一套专用驱动才能启动,不构成新的可独立 onboard 的 lib,因此本次只写这条负面结论,不新建 libs/<slug>/ 目录。

验证过程

1. 代码血缘对比limalib/lima 和本 lib 来源的 fluffos/lima 是两个独立的 GitHub 组织下的仓库(limalib/limadefaultBranchRef/parent 显示不是 fluffos/lima 的 fork), 但目录结构和核心文件几乎一致——两边的 secure/check_config.c 逐行 diff 下来,除了版权头文字和版本号字符串("MudOS"→"FluffOS"、 config.limaconfig.mud)之外,need() 检查列表完全相同, 证明是同一 LIMA 血缘的演进版本,不是独立重写。文件数 limalib/lima 1534 个 vs fluffos/lima 1969 个(前者砍掉了不少 demo 内容,新增了 obj/admtoolobj/tasktoolstd/racecmds/guild 等框架性目录),属于同一代码库的功能增补/精简, 不是从零重写的替代架构。 2. 直接读 limalib/lima 自带的 lib/secure/check_config.c—— 这就是 LIMA 系 mudlib 用来拒绝在不兼容驱动上启动的自检文件。 除了沿用 §7.46 记录的五项(NO_LIGHT/NO_ADD_ACTION/NO_WIZARDS/ undef OLD_ED/undef PACKAGE_UIDS),还新增了几项检查 (SANE_EXPLODE_STRING 需定义、CAST_CALL_OTHERS 需未定义、 OLD_RANGE_BEHAVIOR 需未定义、MUDLIB_ERROR_HANDLER 需定义、 ARRAY_RESERVED_WORD 需未定义、PACKAGE_CONTRIB/PACKAGE_PARSER 需定义)——但这些新增项本项目共享驱动(~/src/fluffos/build-debug) 原本就满足,不构成新的冲突点;真正冲突的仍然是那五项经典要求, 一个字都没变。 3. 实测启动:用本项目的 scripts/convert_lib.shlimalib/limalib/ 转成 .lpc(UTF-8 源码,1407 文件已是 UTF-8、0 需要转码,127 个二进制文件跳过,行为和 fluffos/lima 转换时几乎一样),配上一份仿照本 lib config.fluffos 改路径/端口 的临时配置,直接用本项目共享的标准驱动~/src/fluffos/build-debug/src/driver,未加任何特殊 flag)尝试 启动——simul_efun/master 加载阶段立即被 check_config.lpccreate()error() 中止,实际报错文本:

`` *Bad driver configuration: ********************************************************** * You have incorrectly compiled the FluffOS driver. This * * driver is not compatible with the LIMA mudlib. Please * * make the following changes to 'local_options' ) in the * * driver source, and recompile. * ******************************************************** #define NO_LIGHT is required for LIMA libs. #define NO_ADD_ACTION is required for LIMA libs. #define NO_WIZARDS is required for LIMA libs. #undef OLD_ED is required for LIMA libs. #undef PACKAGE_UIDS is required for LIMA libs. ******************************************************** The simul_efun (/secure/simul_efun) and master (/secure/master) objects must be loadable. ``

和 §7.46/本 lib 上文记录的 fluffos/lima 症状完全一致——不是 "modernized" 架构层面移除了这个假设,只是版本号/驱动兼容性提示文字 更新了而已(README 里"modernized"、"run latest FluffOS driver" 说的是能跟着最新版 fluffos 驱动源码(adm/dist/fluffos 子模块跟踪 fluffos/fluffos.git)编译,而不是摆脱 NO_LIGHT/NO_ADD_ACTION/ NO_WIZARDS/OLD_ED/PACKAGE_UIDS 这套架构假设)。

有用的推论(供未来参考)

limalib/lima 要求的五项和本 lib 已经解决的 fluffos/lima 要求 完全相同,所以本 session 已经建好的 ~/src/fluffos-lima/build-debug(worktree,见上文"§7.46 的后续"一节) 理论上不需要任何改动就能同时满足 limalib/limacheck_config.c—— 如果未来真的要把 limalib/lima 也收进本项目(例如作为它自己独立的 lib,因为它的功能集/demo 内容和 fluffos/lima 已经有实质差异,不是 纯粹的重复),可以直接复用这个驱动 worktree,不必重新摸索 flag 组合。 但这次任务的范围只是回答"是否解决了驱动 flag 冲突"这一个问题, 结论是否定的,所以没有走完整的 onboard 流程(没有 convert_lib.sh 之后的编译修复循环、没有真实注册验证、没有分配 number/port、 没有新建 libs/<slug>/ 目录)。

深度功能测试 / Deep functional test (2026-08-27, §10.7)

这个 lib 之前只做过"能启动/编译"级别的验证(见上文"定义完成的验证 记录"一节)——本轮是第一次按 AGENTS.md §10.7 的方法论做一次真正连续 的真人playthrough(真实注册 → 探索 → 战斗 → 门派/公会交互 → quit/隔一段真实时间后重连 → 查日志),用专用的 ~/src/fluffos-lima worktree 驱动(已存在,直接复用,未重新编译)。

Lima 本身是 FluffOS 官方的框架/演示 mudlib,不是一款有完整门派/任务 系统的"游戏"——help newbie 就是原版英文 Zork 式通用教程,核心可测 系统是:注册/建角、AUTO_WIZ巫师身份、导航、skills(战斗中自动 熟练度成长)、kill战斗、GUILD_GUARD门禁、talk toNPC 对话、 questsquit/重连。测试角色:账号 TestHero/TestPass123,角色 Aidan(human),全程走过注册六项资料 → 建角(种族选择)→ s选中 → p进入游戏,落地 Grand Hall;另建了一个非管理员的 questfinal/ Rowan 角色专门复测下面的 bug 修复(确认不是只有先前角色的残留状态 碰巧绕过了问题)——两个测试账号连同它们的存档在验证完成后都已按本 项目惯例清理data/players/{a,r}/data/links/{t,q}/、以及 GUILD_D 因这次测试而首次落盘的 data/daemons/guild.o),只保留种子 fluffos 管理员账号;data/secure/{access,access_backup}.odata/secure/LOGdata/daemons/last_login.odata/news/* 里因登录/公会daemon初始化产生的残留字段也已用 git checkout 还原,最终 git status 只剩两处真实代码改动。

发现并修复的真实 bug

1. std/guild_guard.lpchandle_blocks() 对一个从未真正被 GUILD_D 定义过的公会名,会把驱动的未捕获 error() 直接甩给玩家, 导致"从被公会守卫挡住的房间试图离开"这个完全普通的移动动作每次必 崩溃。

2. daemons/guild_d.lpcload_missions()/load_favors() 两个函数在 GUILD_D 第一次被懒加载时必定崩溃,因为它们引用的两个 目录在这个仓库里根本不存在——修复 #1 直接触发并暴露了这个第二层 bug。

测试覆盖:干净通过的部分

已知但未修的观察项(不确定是否算 bug,按惯例只记录不改)

Upstream PR 审计(2026-08-31,standing queue 项目)

project_fluffos_org_upstream_pr_queue.md 的标准流程,把上文"编译 期发现的真实 bug"一节里已经在本地 work/ 修好的 6 处 bug 逐一核对 是否需要(也能否)提交回上游:

- 核实同一 LIMA 社区已迁移到 github.com/limalib/lima(非 fluffos/lima 的 GitHub fork 关系,但同一 Discord #LIMA 频道、 同一品牌"limamudlib.dev",且本文件前面"附录(2026-08-26)"一节 已经做过一次代码血缘对比,确认是同一 LIMA 代码库的延续版本,非 独立重写)——直接 clone 核对,std/modules/m_gettable.c/ std/modules/m_exit.c/obj/usermenu/usermenu.c 三个文件对应位置的三处 bug 逐字节存在,尚未修复(master/ stable 两个分支都确认过),且该仓库尚无任何提及这三处的 open/closed PR。判定为这三处 fluffos-org 遗留 bug 的实际可提交 对象,改为向 limalib/lima 提交: PR #49set_droppable)、 PR #50eval_dest private→protected)、 PR #51confirm_decision 赋值/比较符)。

Shop (2026-09-04 librarian slice)

Biff's General Store (/domains/std/Shop) is live. Seeded admin fluffos / Mud@2026 (user menu p to enter; character already selected) started with empty pockets (money → "only lint"). eval this_body()->add_money("gold", 50.0) credited 50 gold. goto /domains/std/Shop, list showed Biff's stock: amber ale and red apple at "no gold", dull sword at 1 platinum, red/blue sticks at 2 copper. buy apple from biff completed but is a zero-price food (query_value() from uneaten eats × heal, heal is 0). buy sword from biff was a real paid sale: "You buy a dull sword for 1 platinum. You give 10 gold to Biff the Shopkeeper." Inventory: dull sword + red apple. money 50→40 gold (platinum factor 10). No programming bug.

拜师: N/A. This is a FluffOS reference/demo lib, not a sect/family game. Live probes: apprentice / become / 拜师 → "I don't know the verb"; join → parser "A valiant attempt"; help guild has no player topic (only wizard guild_d). GUILD_D stock guilds are still not loaded (same as the 2026-08-27 guild_guard/sorcery finding). School rooms are a wizard-coding tutorial, not an apprenticeship.