Journey West: Enhanced Edition

✅ 可玩

幻想西天加强版

hxxtjqb

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

▶ 开始游玩 · Play Now

游戏内标题为"西行战记"(MudOS v22pre11 MudLib Build 3310),一个西游记题材的传统 GB/BIG5 双编码 ES 血统 mudlib,严格取材《西游记》神话世界观——三十三天、蟠桃园、蓬莱、南海、天宫等取经沿途地标都是游戏里真实可达的场景,与本项目"三界神话"系家族(编号 99-101 等)地名风格相近,却是完全独立的代码库。注册时会先问玩家"是否为中小学生或更小年龄",答"是"会被直接劝退,是这批收录档案里对未成年访问处理最直接的一例。月宫场景(`d/moon/`)里还放置了诗词类物件,为以战斗/探索为主的地图增添了一点文学化的细节。

English

The in-game title is "Chronicle of the Journey West" (MudOS v22pre11 MudLib Build 3310) -- a traditional GB/BIG5 dual-encoding ES-lineage mudlib built closely on Journey to the West's own mythology: the Thirty-Three Heavens, the Garden of Immortal Peaches, Penglai, the South Sea, and the Heavenly Palace all appear as real waypoints along the pilgrimage route. It shares its naming style with this project's "Three Realms Mythology" family (numbers 99-101) but is a genuinely separate codebase, not a shared engine. Registration opens with a real-time GB/BIG5 encoding choice, then asks outright whether the player is a school-age minor -- answering yes turns the player away on the spot, the most direct under-age gate found anywhere in this collection. The moon-palace scene (d/moon/) is furnished with a poem object, a small literary touch on top of the usual combat/exploration map.

README

内容亮点

注册流程

进入后先选择编码 GB/BIG5(gb/big5)→ 是否为中小学生或更小年龄的提 醒(yes/no,答 yes 会被劝退)→ 英文 id(键入 New 触发新玩家注 册,3-8 个小写英文字母)→ 中文名字(1-6 个汉字)→ 密码(≥5 字元) → 确认密码 → 电子邮件地址 → 性别(m/f)→ 天赋数值调整菜单(选 9 接受当前设置,再输入 y 确认)→ 进入游戏世界。

本次修复的关键 bug

管理员账号 / Admin account

管理员名单存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常 注册流程创建,"目前权限:(admin)" 已在游戏内确认显示正确。

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

本地运行

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

游戏端口:40177

NOTES · 移植与修复记录

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

西游记题材的 ES 血统 mudlib(MudOS v22pre11 MudLib Build 3310),游戏内标题为"西行战记",连线时有一个实时的 GB/BIG5 双编码选单。修复的 bug:(1)经典的 §6.6 convertd.lpc 希腊字母表漏斜杠错字,45 处,导致每次连线的横幅 cat() 都会崩溃;(2)logind.lpc 里经典的 §8.1 check_legal_name() 字节数没减半的长度界限+i%2==0 门槛+尾部切片 bug(is_chinese() 本身已经是正确的码点判断);(3)实时存在的 GB/BIG5 编码选单 bug(§8.7)——选 BIG5 会在之后每一行都刷出"Invalid GB code",已把两个选单选项都对应到 GB 直通编码修复。管理员账号(fluffos/Mud@2026)通过真实注册流程 + adm/etc/wizlist 播种,游戏内"目前权限:(admin)"显示确认生效。完整的注册→look→score→quit 流程在排版格式化前后各验证过一次,用的是真实中文名字(秦风)。格式化工具发现 2 个档案(d/moon/obj/poem.lpc、u/bmw/task/taskd.lpc)带有转档之前就存在的损坏字符串字面量(一段没有结束的诗词字符串,和一段写死在源码里的分页器输出痕迹)——已还原格式化工具对这两处的重新加空格处理,而不是在已有损坏之上继续叠加,其余问题按 WASM 验证范围之外处理,未修。

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

深度功能测试(2026-08-17,round one)——干净通过,零 bug,但揭穿了一个 tmux/telnet 测试工具的严重可靠性问题

第一次对这份档案做完整的 §10.7 深度游玩测试(注册→探索→战斗→死亡/ 复活→留言板发帖),全程零真实 bug:

重要的工具方法教训:tmux + telnet 对这份档案(也可能更广泛)不

可靠到会制造假 bug

score/hp/inventory,以及任何不存在的指令,透过 scripts/tmux_mud.shtelnet -E 起的会话)测试时全部只显示空白 ——没有任何报错、没有"什么?",看起来像是一个极其严重的"指令派发 静默失效"的 bug。深挖了 query_entire_dbase()error_handler()default error message 配置、report_error() 频道广播等好几层, 一度高度怀疑是驱动侧的静默吞错误配置缺陷。最终用一个独立的原始 Python socket 连线重现同一操作序列,score/hp/inventory 全部 返回完整、正常的内容——证明这完全是本地 telnet 客户端的问题,不 是这份档案的 bug,和 nt6 round four 发现的 ^] escape 模式问题是 同一类,但这次是静默丢弃后续输出、不显示任何提示,比那次更隐 蔽,telnet -E 也没能解决它。

本轮之后改用单次 Python socket.create_connection() 脚本驱动整段 测试(一个脚本内完成"连线→登录→若干条指令→断线"这一整个逻辑阶 段,而不是每条指令都开一条新连线)——既保留了跨指令的会话延续性 (不违反"别用一次性 Python 脚本"的既有教训的精神),又完全避开了 telnet 客户端这层不可靠的中间人。建议以后凡是在这个项目里做 §10.7 深度游玩测试,默认就用这个原始 socket 脚本方式,而不是 scripts/tmux_mud.sh——tmux+telnet 现在已经在两个互不相关的档案 上各自制造过一次足以误导排查方向的假象。

§7.100 sweep (2026-08-19)

Fixed the corpus-wide inherit ROOM; ... replace_program(ROOM); redundant-replace bug (AGENTS.md §7.100). 295 live occurrences deleted: 291 via scripted sweep (fix_710_room.py), plus 4 hand-fixed roommaker-tool occurrences across 2 tool copies (clone/misc/roommaker.lpc — simple variant; obj/roommaker.lpc — "room_code"/str 3-occurrence variant). 3 already-commented-out instances left untouched. No real .lpc source found under work/data/. Verified via build-debug driver boot: clean compile, port 40177 listening, zero new "cannot replace"/"cannot bind" debug.log lines. Pre-existing untracked test-account debris (data/{login,user}/{f/fluffos,q/qintest}.o) confirmed left untouched by git status review before staging.

§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.

AGENTS.md §7.19: enable_player() reentrancy guard (2026-09-01)

Same corpus-wide bug class as mhxy/wuhanzhan: feature/command.lpc's enable_player() wraps enable_commands() and is unconditionally reachable from an NPC's init() via setup()/reset_me() (confirmed on this lib's own d/*/npc/zhangmen*.lpc-family NPCs, matching mhxy's originally-documented d/xueshan/npc/zhangmen.lpc pattern). Calling enable_commands() on an object that's already living() makes the driver re-invoke that object's init() as a side effect; since init() calls back into enable_player(), that is genuine same-call-stack reentrancy that repeats until "Too deep recursion" aborts a room's first-ever visit.

Fixed with a true reentrancy flag (nosave private int in_enable_player_now;), NOT a bare if (living(this_object())) return; guard — this lib's feature/damage.lpc revive() and cmds/std/sleep.lpc wakeup()/wakeup2() all legitimately re-invoke enable_player() while the object is still living() (that's how a fainted/asleep character gets commands back), so a living()-gated guard would silently break every one of those real re-enables. enable_player()'s single body has no early return statements, so the flag is set at entry and cleared once, before the function's fall-through end. Verified with a single-file lpcc compile check (exit 0, no errors) against feature/command.lpc.

深度功能测试 round three batch 4 新角度测试 (2026-09-01)

Round one(2026-08-17)已经完整跑过注册→探索→战斗→死亡/复活→留言板 发帖这条主线,且干净通过。本轮刻意换一个完全不同的测试角度,按照 项目当前的对抗式/边缘输入 + 断线时序 + 经济系统 + 邮件系统的清单来 测试,使用原始 Python socket.create_connection() 脚本驱动(继承 round one 自己踩过的教训:scripts/tmux_mud.shtelnet -E 在这 份档案上会静默吞掉部分指令输出,不可靠)。驱动跑在 config.fluffos (端口 40177),全程逐动作 grep log/debug.log

测试角度:注册流程对抗式输入(超长英文 ID、非 UTF-8 垃圾字节、 空输入、连续非法 ID 触发洪水防护 id_count>6 踢线)、中文名字边界 (空、纯 ASCII、单字合法名)、std/money.lpcquery_autoload()/ autoload() 契约是否像 fysjmb 一样被注释掉(AGENTS.md §7.99 严重 货币销毁类 bug)、邮件系统(obj/mailbox.lpcmail/from/ readmail/discard)、金钱经济在 quit/重连后的持久性、巫师 call 指令对在线玩家对象的跨对象调用。

发现 1(已修复):adm/daemons/logind.lpcget_name() 里一

条遗留的 printf("%O\n", ob) 调试输出,直接把登入物件的内部路径 (如 /obj/login#25)打印到刚设定好中文名字的新玩家屏幕上——AGENTS.md 既有的 §7.34 bug class 的一个新实例

用真实中文名字("秦风测二")走完整注册流程,在设定名字、系统提示 "请设定您的密码:"之前,屏幕上先额外多打印了一行 /obj/login#25 (活体验证,round three batch 4 之前从未在这份档案上确认过, AGENTS.md §7.34 现有清单里也没有 hxxtjqb)。定位到 adm/daemons/logind.lpc:1191(修复前):

  printf("%O\n", ob);

  ob->set("name", arg);

printf("%O 是没有任何说明注释的开发期调试语句,混在一串正常的玩家 提示 write() 之间,直接把驱动内部的对象路径吐到连线画面上。按 §7.34 已确认的标准修法,整行删除。修复前后各跑一次完整注册(gbnonew→英文 ID→中文名字),修复后画面干净地直接跳到"请设定您的 密码:",log/debug.log 全程无新增报错。

发现 2(已修复,AGENTS.md §4.3 既有 bug class 的新实例):

adm/simul_efun/file.lpclog_file() 引用一个从未真正创建的 /log/nosave/ 目录,导致巫师 call <玩家>-><函数>(...) 指令对任何 在线玩家对象的跨对象调用都会执行时段报错并整个中止——call_other() 本身根本没机会执行

用管理员账号(fluffos/Mud@2026,真实注册+wizlist 播种)对着一个 同房间的在线测试角色(advteste)执行 call advteste->add_money("coin",500),屏幕上直接报出:

执行时段错误:*Wrong permissions for opening file /log/nosave/CALL_PLAYER for append.
"No such file or directory"
...
呼叫来自:/adm/obj/simul_efun.lpc 的 log_file() 第 8 行
调用参数:log_file("nosave/CALL_PLAYER", "秦道人(fluffos) call 秦风测二(advteste)->add_money(...)...")
呼叫来自:/cmds/wiz/call.lpc 的 main() 第 42 行

这正是 AGENTS.md §4.3 已经记录过的经典形状:convert_lib.sh\bstatic\bnosave 全局替换是按单词边界做的正则,连字符串字面量 里的 "static/..." 路径前缀也被一起改成了 "nosave/...",但仓库里 真正被播种的目录是 log/static/ls log/static/ 能看到 CALL_PLAYERCRASHESforce_playerpromotepromotionPURGESUICIDE 这些真实的历史日志种子文件),log/nosave/ 从未 存在过。对照 raw/hxxt/cmds/wiz/call.c 确认原始未转档源码里这一行 本来就是 log_file("static/CALL_PLAYER", ...)——证实是转档期间的 误伤,不是原始设计。

全档案 grep "nosave/ 命中 13 个文件 / 17 处,逐一对照 raw/hxxt/ 里的原始 .c 源码确认都应该是 "static/...vi.c#define LOGFILE "static/VI" 也同样确认):adm/daemons/logind.lpc (本条已单独按发现 1 处理)、adm/daemons/securityd.lpcadm/obj/master.lpc(4 处 CRASHES)、cmds/adm/promote.lpccmds/adm/xpass.lpccmds/arch/purge.lpc(2 处)、 cmds/arch/purge2.lpc(2 处)、cmds/arch/purgehouse.lpccmds/eld/full.lpc(已注释掉的调用,一并改正)、 cmds/std/suicide.lpccmds/usr/suicide.lpccmds/wiz/call.lpccmds/wiz/force.lpcfeature/vi.lpc。全部机械改回 "static/...

另外按 AGENTS.md §4.3 已确立的加固手法,给共享的 log_file() simul_efun 本身也加了一道 assure_file() 前置调用(file.lpcassure_file() 定义在 log_file() 之后,补了一行前向声明):

void assure_file(string file);

void log_file(string file, string text) {
  assure_file(LOG_DIR + file);
  write_file(LOG_DIR + file, text);
}

这样以后任何一个引用了从未创建过的目录的 log_file() 调用点都会 自愈而不是崩溃。活体验证:修复前对在线测试角色执行 call advteste->add_money(...) 直接执行时段报错、call_other() 从未真正执行;重启驱动加载修复后的代码,同样的指令干净地打印出 /obj/user#28 ("秦风测二")->add_money("coin", 500) = 0log/debug.log 全程无新增报错。

排查过程中澄清的两个误报(记录以免以后重复踩坑)

未发现问题的角度(活体验证过,诚实记录)

本轮共发现并修复 2 个真实程序 bug(§7.34 调试信息泄露的新实例、 §4.3 log_file() 缺失目录导致 call 指令崩溃的新实例),均已现场 用修复前/修复后的 debug.log 对比 + 实际游戏内指令输出验证。两个 bug class 都已经在 AGENTS.md 里有完整记录,本次不需要再新开 bug-class 条目,仅需要在这两节里补充 hxxtjqb 这个新实例(如果后续 批次也在别的库发现,再由那个批次自己写补充说明)。

深度功能测试(2026-09-04,round three,shop + 拜师)

新角度:南城客栈购物 + 方寸山云清拜师。2026-09-01 测过货币 quit 持久 和邮件,没有走 list/buy,也没有拜师。这是 ES/幻想西天血统(游戏 内标题「幻想西天」),不是夕阳再现。端口 40177。第一输入是 GB/BIG5 选单,发 gb,然后「是否中小学学生」发 no,再英文 id。

实测过程

管理员 fluffos / Mud@2026(权限 (admin))。既有存档带着 kee:-1 / disable_type:"<昏迷不醒>"(2026-08-17 被朱睛冰蟾打死留下 的),登录后会立刻「眼前一黑」;等「又有了知觉」再 full 才恢复。 clone /obj/money/gold 可用。

goto /d/city/kezhan(南城客栈,店小二 d/city/npc/xiaoer.lpcF_VENDOR_SALE)。list 炸鸡腿八十文钱 / 桂花酒袋一两银子 / 花生豆 二十文钱等。本库 buy 格式是 buy <物> from <人>,不是光 buy jituibuy jitui from xiaoer 成功(「你向店小二买下一根炸鸡腿」)。当场 i 是九十九两银子 + 二十文钱 + 炸鸡腿。

goto /d/lingtai/inside6,云清(d/lingtai/npc/yunqing.lpc)无门槛 收徒。apprentice yun 一次成功:恭喜成为方寸山三星洞第四代弟子。 score 职称「方寸山三星洞第四代弟子」、师承云清。菩提祖师只收本门 高道行弟子,不要拿他当新手拜师点。cmds/usr/save.lpc 真正写盘,10 秒内再 save 是「你迟点才可以储存」。save 后杀驱动冷启动再登录,门派/ 师傅/银子铜板都在。炸鸡腿未进 autoload。

本轮没有新的 programming bug。巫师登录时大量「编译时段错误」其实是 #pragma 警告被 log_error() 打到巫师屏幕上,不是执行时段崩溃。