War of Demons and Gods

✅ 可玩

妖神之争

yszz

🔑 fluffos / Mud@2026 更新 245bd97 2026-09-04 源码 下载 ZIP

▶ 开始游玩 · Play Now

一款以"西游记"神话世界为背景的武侠/仙侠向 MUD,新角色由西行取经的框架切入,起手在长安城"南城客栈"落脚。

English

A xianxia MUD set in the mythological world of Journey to the West, with new characters entering through the pilgrimage-to-the-West framework and starting at the South City Inn in Chang'an. Its eight-stat talent system (Strength/Courage/Comprehension/Spirituality/Composure/Looks/Constitution/Fortune) feeds a two-camp, ten-sect roster split along the novel's own good-versus-evil axis: five "Divine" sects (Five Villages Temple, Moon Palace, Dragon Palace, Putuo, Fangcun Mountain) against five "Demon" sects (Bottomless Cave, Xuanyuan's Ancient Tomb, Water Curtain Cave, Great Snow Mountain, the Underworld), each favoring different builds of fist/weapon/spell/internal-power/lightness-skill and gated on gender and Looks — the newbie manual even notes some demon sects specifically want a LOW Looks score. Death is a full afterlife ritual: Judge Cui Jue of the Vermilion Brush escorts the ghost to the Yin-Yang Boundary, with automatic revival after a short wait.

README

内容亮点

深度功能测试新发现的 bug(详见 NOTES.md)

adm/daemons/logind.lpc 里有一行调试用的 printf("%O\n", ob), 紧挨在设定中文名字之前,每一个新玩家注册时都会看到(AGENTS.md §7.34)。已删除。

在线试玩

https://mudlibs.fluffos.info/yszz/

管理员账号 / Admin account

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

本地运行

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

游戏端口:40192

NOTES · 移植与修复记录

深度功能测试(第二轮,2026-08-03)

之前的会话只测过注册流程,本轮做了完整的 §10.7 深度功能测试。 proactive 检查 AGENTS.md 已归档的四类常见坏味道:feature/ command.lpc(以及一份 edit/ 目录下的镜像副本,核实不是生效路 径)里的"private nomask command_hook"只是历史注释保留的旧代码痕 迹(// private nomask int command_hook(...)),真正生效的声明 早已是干净的 nomask int command_hook(...);命中了一处 adm/ daemons/logind.lpc 里的 printf("%O") 调试残留(新增 yszz 到 AGENTS.md §7.34 确认实例列表);未命中 unguarded MESSAGE_D->、 stat/water 键名、§8.9 坏 age 判断。

完整流程验证:注册全新角色(沐妖神/id yszzdive),从"南城 客栈"起步,hp 确认食物/饮水/气血/精神槽均满值;向"疥顶小僧" (这批西游记题材姊妹档案里反复出现的同一个高战力 NPC, combat_exp 50000)发起战斗——完整交手数回合后被击昏迷致死("你 死了"),送往"阴阳界"由"朱笔判官 崔珏"接引,明确提示"你莫乱跑, 画了生死簿,我好送你还阳"(和 bmxkx2001 那次发现的"鬼魂在复活 过程中被强制移动会永久卡死"是同一类设计警示,但本次静候没有被 任何其它系统打断,正常复活成功,score 数据完整);quit 干净 退出。全程 debug.log 零报错。

未覆盖范围:拜师(五庄观/月宫/龙宫/普陀/方寸山/无底洞/轩辕古 墓/水帘洞/大雪山/地府共十个门派可选)、西行取经任务线、留言板因 时间原因未实测。

深度功能测试补测:拜师/西行取经/留言板(2026-08-24)

补测第二轮 NOTES 标记的三处未覆盖范围。

留言板:南城客栈留言板 post <标题> 进入内建编辑器,输入正文 以单独一行 . 结束,留言完毕look board 正确显示新留言,作 者本人 discard <编号> 成功删除。round-trip 干净,无 debug.log 报 错。(测试中途一次通过 scripts/tmux_mud.sh multi 发送多行编辑器 正文时, 结尾的中文句子在 telnet 层被截断、误触发本地 telnet 客户端的 Ctrl-] 转义——这是已知的 tmux/telnet 多字节透传 假警报,不是驱动或代码问题;改用一次性发送的原始 Python socket 脚本后单行/多行中文输入都稳定无误。同样的假警报又在 ask yin about 陈光蕊 上重现了一次( 被替换成 ),换用 raw socket 脚本发送同一条命令后文字完全正确,NPC 对话也正常,确认属于同一传 输假警报,不是取经任务线代码的问题。)

拜师(选测月宫,嫦娥):新角色(女性,容貌 30)goto/summon 传送至嫦娥所在的"长思馆",apprentice change 一次性走完全套流程 (嫦娥的 attempt_apprentice 检查性别+容貌门槛通过后自动 recruit),score 的"师傅"字段正确从"鬼才知道"变为"嫦娥",并 获得师门长剑。十个门派共用同一套 feature/apprentice.lpc / cmds/std/{apprentice,recruit}.lpc 机制,本次仅实测月宫一支,但 逻辑路径对全部门派通用。

发现并修复一个真实的 programming bug(非平衡性/内容问题): cmds/std/apprentice.lpc 里"对方已经用 recruit 表态愿意收我为徒" 分支(ob->query_temp("pending/recruit") == me 时),判断是否为 "背叛师门投入新门派"时直接比较 me->query("family/family_name") != ob->query("family/family_name"), 没有先判断 me(申请人)本来就有没有 family——对于第一次拜师、 从未加入过任何门派的角色,me->query("family/family_name") 恒为 0,永远不等于新师父的门派名,导致每一次「正常首次拜师」都被误判 成「背叛师门投入别人门下」,弹出错误的台词且把 score 清零。姊 妹指令 cmds/std/recruit.lpc 里对称的分支(me->recruit_apprentice 一侧)正确地先用 (ob->query("family")) && (...) 守卫, apprentice.lpc 漏掉了同样的守卫,help 文本本身也写明"你已经有 了师父,又背叛师门投入别人门下"才会触发这个惩罚——代码与文档意 图不符。加了同样的 me->query("family") && 守卫修复。

修复前后均现场复现验证:造出两名全新无门派角色,让已拜入月宫 的 yszzcy 先用 recruit <目标> 主动收徒(模拟玩家师父主动招募 从未拜师的新人这一常见场景),目标再用 apprentice yszzcy 确 认——修复前,回应是错误的"你决定投入云裳仙门下!!"(背叛台词); update /cmds/std/apprentice 热更新代码后,同样操作对第二个全新 角色正确显示"你决定拜云裳仙为师。"(正常拜师台词)。两次全程 debug.log 零报错,确认是纯逻辑 bug,不是编译/崩溃类问题,但确有 实际错误行为(错误台词+错误清零 score)。

西行取经任务线doc/help/newqujing 里有完整的攻略文档,全线 共 36 "关"(obstacle/number),score 里"任务行动篇"栏正确显示 "你尚未踏上西行大道"(obstacle/number == 0)。实测了第一关"江 州/金山寺"的头两步:goto /d/jz/fzroom 找法明长老 ask faming about 血书 正确给出反应并交出信物;goto /d/jz/in 找殷温娇 ask yin about 陈光蕊 正确触发她的伤心台词。两步均无崩溃、无 debug.log 报错。后续关卡(双叉岭杀虎、nianjing 念经、流沙河跳 水等)因深度游玩成本高(帮助文档标注全线需要上千年道行/极高战力 才能推进到后期关卡)未继续深入,但已验证任务线的入口和早期节点 是可达、可交互、无编程错误的。

测试用角色(yszzcy/yszztsb/yszztsc)及其存档已清理;南城客 栈留言板测试留言已通过 discard 删除。

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

WASM 修复:修好了 §8.1 GBK 字节区间 is_chinese()/check_legal_name() bug(这个驱动下 str[i] 是一个码点,不是一个 GBK 字节——真实的中文名字会被静默拒绝);给 band.lpc 的 is_banned()/create_char_banned() 打上了本地回环放行补丁;通过 adm/etc/wizlist 把 fluffos/Mud@2026 播种为 (admin)。在 WASM 下用一个真实的中文名字(秦风)完整验证了注册+look/score/quit,管理员账号的 update 指令也验证可用。

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

§7.100 sweep (2026-08-19)

Fixed the corpus-wide inherit ROOM; ... replace_program(ROOM); redundant-replace bug (AGENTS.md §7.100). 305 live occurrences deleted: 303 via scripted sweep (fix_710_room.py), plus 2 hand-fixed roommaker-tool templates (clone/misc/roommaker.lpc, obj/roommaker.lpc — both simple string-builder variant). 7 already-commented-out instances left untouched. No real .lpc source found under work/data/. Verified via build-debug driver boot: clean compile, port 40192 listening, zero new "cannot replace"/"cannot bind" debug.log lines. Pre-existing untracked test-account debris (data/{login,user}/y/yszzdive.o) confirmed left untouched by git status review before staging.

``§7.112`` residual-gap closure (2026-08-20)

Corpus re-scan (grep -rl 'call_out("death_stage"' ... | filter for missing guard) found unguarded init()-scheduled death_stage() call_out chain(s) in d/death/npc/wgargoyle.lpc that the original two-wave sweep (see AGENTS.md §7.112) missed -- same reconnect-triggered duplicate-chain bug, different filename/lineage. Added the standard query_temp("death_stage_active")/set_temp/delete_temp re-entry guard, adapted per file's own exit points. Compile-verified via lpcc --batch.

§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): 4 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.

AGENTS.md §7.19 sweep (2026-09-01): enable_player() reentrancy from init()

Same corpus-wide bug class as mhxy/wuhanzhan (AGENTS.md §7.19): this lib's feature/command.lpc enable_player() wrapper (around the raw enable_commands() efun) is reachable from an NPC's init() via a redundant create()-then-init()-calls-setup() (or reset_me() calling setup()) chain -- confirmed live via a static scan of every init() body in this lib: 48 NPC/item files call setup() directly or via reset_me() from init(), after create() already called setup() once (which already made the object living()). Calling enable_commands() a second time on an already-living() object makes the driver re-invoke that object's own init() as a side effect, which re-enters this same chain while the original call is still on the stack -- genuine reentrancy, crashing with "Too deep recursion" (most likely to surface on an NPC's first-ever preload/compile).

feature/damage.lpc's revive() and cmds/std/sleep.lpc's wakeup1()/wakeup2() call enable_player() again while the object is still living(). This confirms a bare if (living(this_object())) return; guard would be the WRONG fix (it would silently break that legitimate re-enable) -- used the same true reentrancy-flag fix as mhxy instead: a nosave private int in_enable_player_now; set for the duration of the wrapper's body, guarding only genuine same-call-stack reentrancy while leaving every legitimate re-enable (revive/wakeup/disguise) unaffected. feature/command.lpc's enable_player() had a single fall-through exit (no early returns), so one guard-at-top + one clear-at-bottom pair was sufficient. Verified via a single-file lpcc --batch compile check (PASS) -- not individually live-boot-tested.

深度功能测试(2026-09-04,shop)

Live native pass on port 40192. 2026-08-24 already did 月宫嫦娥拜师; this slice is shop-only. First send is gb (banner “Select GB or BIG5 (gb/big5)”), then id fluffos / Mud@2026 ((admin), lands in 巫师会议厅). clone /obj/money/gold works.

南城客栈 店小二 (u/city/npc/xiaoer.lpc, F_VENDOR_SALE) list already showed 炸鸡腿 80文 (vendor_sale.lpc #include <dbase.h>). Bare buy jitui did not: cmds/std/buy.lpc auto-picks is_vendor() in the room, but F_VENDOR_SALE never defined it (only feature/vendor.lpc did). Help text requires buy <item> from <someone>; without is_vendor() the short form always printed the usage line. Added int is_vendor() { return 1; } (CRLF preserved). After reboot, buy jitui purchased 炸鸡腿 and changed 1 黄金 into 99 两银子 + 20 文. No 丐帮 refuse (this vendor has none).