Demon Angel II

✅ 可玩

国家制度的MUD DA

gjzddmudda

🔑 fluffos / Mud@2026 更新 9eb7ca0 2026-09-01 源码 下载 ZIP

▶ 开始游玩 · Play Now

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

English

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

README

内容亮点

注册流程

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

本次修复的关键 bug

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

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

管理员账号 / Admin account

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

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

本地运行

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

游戏端口:40122

NOTES · 移植与修复记录

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

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

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

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

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

确认不是 bug 的检查项

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

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

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

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

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

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

真实战斗死亡

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

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

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

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

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

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

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

清理

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

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

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

§7.30 uninitialized-mapping accessor sweep (2026-08-20)

Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2 via round-four testing): 3 accessor(s) in this file returned a raw never-initialized mapping instance variable (defaults to int 0, not ([]), until first assigned), crashing any unguarded keys()/sizeof()/indexing caller for a fresh/untrained character. Fixed at the accessor level (mapp(x) ? x : ([])) per the documented remedy. Verified via lpcc --batch static compile check only (not a live boot) as part of a large mechanical sweep; not individually functionally re-tested live on this lib.

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

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

Two real bugs found and fixed, both verified live:

Confirmed clean / no bug found, despite active testing:

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