Rhapsody Realm (Early Edition)

✅ 可玩

狂想空间

kxkj1

🔑 fluffos / Mud@2026 更新 66a3bd8 2026-10-28 源码 下载 ZIP

▶ 开始游玩 · Play Now

1995 年 9 月 22 日创建的老牌台湾 MUD(创始团队 wade、shorst、jcder 等),属于 ES II 引擎系列(与本项目中的 es1_win、esI、xkx2001、rzrmud、侠客行系列等同宗)。新手从"世界的入口"出发,先决定是否加入某个帮派再闯荡江湖,创角时要在 8 项属性间手动分配总计 160 点天赋点数,而非常见的随机重掷;整体节奏偏休闲,还保留着 tintin 客户端脚本支持提示等早期台湾 MUD 特有的界面细节。本项目中还有另一个档案"新狂想空间II"(增加了邮箱注册等更新内容),两者虽然都自称"狂想空间",但经比对是两个不同时期、独立流传的版本,本档案是相对更早的一个存档快照。

English

A venerable Taiwanese MUD founded September 22, 1995 (by wade, shorst, jcder, and others), part of the ES II engine series shared with this project's es1_win, esI, xkx2001, rzrmud, and the Ode to Gallantry series. An early, gang-centric snapshot of the same "Rhapsody Realm" world as this project's kxkj: newcomers start at the "Gateway to the World" and choose whether to join a gang before heading out into the jianghu, character creation is a fully manual budget allocation (8 stats, 160 points, hand-assigned rather than random-rerolled), and registration skips the email step present in kxkj's later edition — a casually-paced, old-school Taiwanese MUD feel throughout, down to built-in tips for scripting the tintin client. Comparison against kxkj shows the two are independently circulated versions from different eras, and this is the earlier of the two snapshots.

README

内容亮点

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

在线试玩

https://mudlibs.fluffos.info/kxkj1/

管理员账号 / Admin account

警告:正式对外开放前请务必修改此密码。

本地运行

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

游戏端口:40063。

NOTES · 移植与修复记录

kxkj1 — 狂想空间 (Fantasy Space)

Archive: 狂想空间.rar (#69). Port: 40063. Status: done (boots clean, full registration flow verified end-to-end twice, real Chinese names both reaching the actual starting room).

Lineage check (done FIRST, per task instructions) — genuinely distinct from archive #53, NOT a duplicate

This archive's own filename ("狂想空间.rar") is literally the same string that archive #53 (新狂想空间II.rar, lib libs/kxkj/) turned out to self-identify as in its own config.fs/banner. Read libs/kxkj/NOTES.md first, then compared this archive's raw contents directly against libs/kxkj/raw/fsII/ (archive #53's already-extracted raw tree) before doing anything else, per the task's mandatory lineage-check instruction:

- adm/obj/master.c: this archive 9,274 bytes (mtime Sep 23 2002) vs #53's 12,615 bytes (mtime Dec 15 2002) — different md5. - adm/daemons/logind.c: this archive 18,796 bytes (mtime Dec 2 2002) vs #53's 32,090 bytes (mtime Dec 15 2002) — nearly half the size, different md5, and missing an email-collection step in the registration flow that #53's copy has (this lib's flow is id→confirm→name→password→confirm→gender→8 attribute points→enter world, no email prompt at all). - adm/daemons/securityd.c: this archive 9,956 bytes (mtime Jul 28 2002) vs #53's 14,869 bytes (mtime Dec 15 2002) — different md5, and a structurally different (simpler, more permissive-by-default) valid_read/valid_write ACL shape (see "Confirmed NOT needed" below). - adm/simul_efun/chinese.c: identical size (263 bytes) but different md5 — this archive's copy is missing a (string) cast on two CHINESE_D-> call results that #53's copy has; the actual is_chinese() logic (the GBK byte-range bug, see §15h below) is byte-for-byte identical between the two.

What this is

Self-identifies in config.fs as 狂想空间 (name : 狂想空间, no "新"/"II") and the live in-game banner confirms the same: 狂想空间承蒙 mineral & elon 协助, 初次架于 1995 9 22 — "with help from mineral & elon, first set up 1995-09-22", crediting founders "wade, shorst, jcder". Same in-game banner text shape as #53's ("感谢...elon & mineral" there), same founding date, confirming both archives really are snapshots of the literal same long-running game, just at different points in its development. Raw archive root directory is named ofs/ (not a recognizable acronym match to the game's own name — kept the pre-assigned working slug kxkj1 since the archive's own top-level dir name isn't a meaningful title either way, matching the project's existing convention of using a phonetic slug of the self-identified Chinese name).

7,947 raw files, 6,323 renamed .c→.lpc. A prebuilt Windows MudOS.exe binary is bundled alongside the source (ignored, per AGENTS.md — our own driver build is used).

Fixes applied

1. AGENTS.md §15h, standard shape, adm/simul_efun/chinese.lpc: is_chinese()'s GBK lead-byte range check (strlen(str)>=2 && str[0]>160 && str[0]<255) rewritten to a CJK Unicode codepoint check (strlen(str)>=1 && str[0]>=0x4e00 && str[0]<=0x9fff) — byte-for-byte the same original bug as archive #53's copy of this exact file. 2. AGENTS.md §15h, check_legal_name() in adm/daemons/logind.lpc: byte-count bound < 2 || > 12 → character-count bound < 1 || > 6 (message text already says "必须是 1 到 6 个中文字", confirming the halved bound); removed the i%2==0 && even-position gate in the per-character is_chinese() sliding check so every character position is checked under UTF-8 semantics. Identical fix shape to #53 (this lib's logind.c clearly shares a very recent common ancestor with #53's copy for this specific function, even though the surrounding file differs substantially in size/content elsewhere). 3. AGENTS.md §15p: adm/etc/preload already had /adm/daemons/network/dns_master commented out in the raw archive — confirmed nothing to remove here (checked proactively before first boot, per standing policy; documenting the check since the archive happened to already be clean on this one). 4. AGENTS.md §15t, all three sub-bugs, ported directly from archive #53's precedent (same driver-inc_open()/legal_path() root causes, confirmed by reading the actual failing files before fixing): - Absolute-path angle-bracket #includes (172 files, e.g. std/armor/cloth.lpc's #include </open/open.h> — literally the same starting-clothes-item file #53 flagged as the highest-impact fix there). Blanket-converted every #include <ABSOLUTE_PATH> to the quoted form (sed -E 's#include *<[[:space:]]*(/[^>]*)>#include "\1"#' after a grep -rlZ scope check), 172 files fixed in one shot, plus one stray leftover .c-extension angle-bracket reference (#include </include/basic_skill.c>, fixed to point at the real .lpc file) that the mechanical convert_lib.sh pass didn't catch since it only fixes quoted ".c" references, not angle-bracket ones. - ..-relative #includes (94 files total: 27 #include "../cold.h" under open/cold/*.lpc, 28 #include <../start.h> under open/start/{npc,room,obj}/*.lpc, 20 #include "../../open.h" under various 2-levels-deep zone dirs, plus smaller one-off groups — capital.h×5, badman.h×4, su.h×2, combat.h×1, ouch.h×1). Resolved each by locating where the target header actually lives on disk (not by guessing at relative-path arithmetic) and converting to an absolute quoted path: - ../cold.h → /open/cold.h did not exist anywhere in the raw archive (a genuine content gap, same as #53's WQA_ROOM/cold.h precedents) — reconstructed a minimal header defining only the two macros actually referenced anywhere under open/cold/*.lpc (COLD_ROOM "/open/cold/", COLD_NPC "/open/cold/npc/" — grepped every COLD_[A-Z]+ use first to confirm no COLD_OBJ is ever referenced and no open/cold/obj/ subdirectory exists, so nothing beyond these two was guessed/added; the room-file layout confirms COLD_ROOM must resolve to the zone's own top dir since sibling rooms are referenced as e.g. COLD_ROOM"home1" and home1.lpc really sits directly under open/cold/, not a nested room/ dir). - <../start.h> → the real /open/start/start.h (exists, defines S_NPC/S_OBJ/S_ROOM, genuinely used by several of the converted files including two personal-wizard-directory copies — u/w/welcome/, u/f/fary/ — of start-zone content). - "../../open.h" (2-levels-deep zone dirs) → /open/open.h in all cases but one: open/snow/room/oldsnow/room3.lpc is nested one level DEEPER than its sibling open/snow/room/*.lpc files, so its literal 2-levels-up target is genuinely /open/snow/open.h (a real, smaller, snow-zone-local header that also exists) — verified this file doesn't actually use any macro from either header at all (only ROOM/LONG, unrelated to open.h), so the choice is inconsequential functionally but the path-depth-correct one was used anyway. One personal-sandbox copy, u/m/mystery/c_box.lpc (a near-identical draft of open/snow/obj/c_box.lpc), has a "../../open.h" that doesn't even resolve correctly BY DEPTH from its own real location (u/m/mystery/, 2-up = u/, no open.h there) — a pre-existing broken copy-paste from whichever zone file it was cloned from; pointed it at /open/open.h to match its sibling instead of preserving an already-broken relative reference. - capital.h/badman.h → real existing /open/capital/capital.h / /open/badman/badman.h (neither macro set is actually referenced by the misplaced/duplicate files that included them — e.g. open/start/room/bad2/3/4.lpc, three files whose own comments and content ("屠娇娇"/"不男不女") read as badman-zone NPCs physically misplaced under open/start/room/, sharing an unused-but-must-still-resolve include with their correctly-located sibling open/badman/room/t3.lpc). - su.h → genuinely missing from the archive entirely (unlike cold.h, this one is independently corroborated by a leftover original-operator debug log found in the raw archive itself, u/b/bigcat/log, which records Cannot #include ../su.h from the *original* pre-conversion mud's own operation — proof this exact gap predates our involvement, not an artifact of conversion). u/o/oda/npc/boss4.lpc's own header comment says // /open/su/npc/boss4.c by oda, confirming an entire /open/su/ zone was planned/referenced but never shipped in this archive (a §13-style missing-zone gap). Reconstructed a minimal /open/su.h defining only the one macro actually used anywhere (SU_OBJ "/open/gblade/obj/", matching the real location of the cup.lpc object u/t/tide/boy.lpc instantiates via new(SU_OBJ "cup")) — boss4.lpc itself never references any SU_ macro at all, so this is enough to satisfy both files without fabricating any of the never-shipped /open/su/ zone's actual content. - combat.h/ouch.h (1 file each) → real absolute paths (/u/f/fary/combat.h, /u/o/ouch/ouch.h) one directory up from each including file's own real location — these would have resolved correctly even under a permissive ..-allowing driver, just converted to the quoted-absolute form this driver requires. - 5 more "../str.h" references (under u/s/server/map2room/*.l) were not touched: these .l files are lex/flex source for a standalone C map-conversion utility (/* Make: lex map.l , gcc -o map lex.yy.c */), never renamed to .lpc, never compiled by the driver at all — correctly out of scope per AGENTS.md's "what counts as LPC source." - inherit appearing after a #included header's (or a bare global's) declaration — found via the lpcc_check.sh sweep (see below), same shape as #53's n_area.h cluster almost verbatim. 5. master.lpc get_include_path() (AGENTS.md §8d/§15o): none existed; added the standard shape (compiling file's own directory + :DEFAULT:) as defensive insurance for any live/mid-connection compile of a same-directory quoted include, alongside the blanket absolute-path conversion above (which resolves unconditionally via merge() regardless of VM context, per §15t's documented caveat that get_include_path() alone isn't sufficient for preload-time compiles). 6. NEW variant of the AGENTS.md §3 counterexample (a "static/..." string-literal path corrupted by the blanket \bstatic\b→nosave keyword sed, same root cause as moniHuafu/archive #57's finding, but never previously documented for THIS lib's own log-directory naming): 31 log_file("nosave/XXX", ...) calls across 15 files (master.lpc's crash() → "static/CRASHES"; several securityd.lpc copies → "static/promotion"; pkd.lpc/call.lpc/purge.lpc/purgewiz.lpc/ xpass.lpc/summon.lpc → "static/pker"/"static/PURGE"/ "static/PURGE_WIZ"/"static/CALL_PLAYERS"/"static/CALL_WIZARD") were silently rewritten to "nosave/XXX" by the mechanical static→nosave sed, since static is a real directory-name substring in these paths, not the keyword. Confirmed the corruption was real (not a false read) by checking the RAW pre-conversion master.c directly (grep -a "log_file" — needed -a since the raw GBK file's control-byte-laden lines otherwise get treated as binary by grep) and finding the literal "static/CRASHES" there, AND by confirming log/static/{promotion,SUMMON,call_wizard,PURGE} are real, pre-existing seed-data files still present in the raw archive under log/static/ — the corrupted references would have permanently orphaned this real on-disk directory. Reverted all 31 occurrences (scoped the fix to lines containing log_file specifically, to avoid touching the two unrelated, correct nos=="nosave" string-comparison hits in u/n/nako/npc/kawali.lpc/u/e/een/kawali.lpc). 7. NEW finding, not previously in AGENTS.md's catalog: bare SAVE_EXTENSION vs the driver's real predefined macro __SAVE_EXTENSION__. 11 files (obj/token.lpc + 3 personal-directory copies, adm/daemons/network/ netmail.lpc, cmds/adm/purge.lpc/purgewiz.lpc + 1 personal copy, include/net/ftpdsupp.h) reference a bare SAVE_EXTENSION macro that is never defined anywhere in this mudlib — while adm/daemons/logind.lpc (which we confirmed compiles and runs cleanly through two full interactive registration tests) correctly uses the double-underscored __SAVE_EXTENSION__ form. Verified __SAVE_EXTENSION__ really is a genuine FluffOS-driver-autogenerated preprocessor constant (grep "SAVE_EXTENSION" ~/src/fluffos/build-debug/src/options.autogen.h → "__SAVE_EXTENSION__", "\".o\""), confirming the 11 files' bare spelling is a real pre-existing bug (likely a naming-convention mismatch against whatever the original MudOS-era driver called this constant) rather than something our conversion introduced. Fixed with a word-boundary sed (\bSAVE_EXTENSION\b → __SAVE_EXTENSION__, safe since \b doesn't match between two underscores, so it never double-mangles the already-correct 8 files using the real name) — all 11 confirmed fixed, zero bare occurrences remain. Worth promoting to AGENTS.md's catalog since it's mechanical, cheap to grep for, and not lib-specific (any lib using an unprefixed constant name where this driver auto-defines a double-underscored one would hit the same gap — grep ~/src/fluffos/build-debug/src/options.autogen.h for the full list of what this driver actually predefines is the reliable way to spot-check any suspiciously-bare constant name like this one). 8. AGENTS.md §15b, exact recurrence of the nitan_ceshi is_killing finding: open/capital/npc/kingwife.lpc (2 call sites) and open/capital/npc/dog0.lpc (1 call site) called is_killing(who) / is_killing(ob) directly (not ->) with an object argument, where feature/attack.lpc's varargs int is_killing(string id) declares a string parameter — every other call site in the lib (60+, matching the established pattern) correctly passes ob->query("id"). Fixed the 3 call sites to is_killing(who->query("id"))/is_killing(ob->query ("id")), resolving these 2 files' own compile failures plus their downstream cascades (open/capital/room/king/kr3-5.lpc/kr4-5.lpc, u/a/anmy/room/kr3-5.lpc, u/t/tide/jar.lpc — all reference/carry these NPCs and failed only because the NPC object itself didn't compile, per AGENTS.md §8g's "one shared root cause, not N bugs" principle, not independent bugs). 9. AGENTS.md §15w, master.lpc's log_error(): gated the this_player(1)-facing live echo on the message NOT containing the substring "warning:" (still writes everything to the log file regardless) — this driver funnels ordinary compile *warnings* (e.g. the harmless "Illegal to declare nosave function" warning from our own §3 fix) through the same apply as genuine fatal errors, and this lib's original log_error() echoed EVERY message it received live to this_player(1) unconditionally, unlabeled as to severity. 10. Related to §15w: master.lpc's error_handler() is declared returning string, with a comment "whatever we return goes to the debug.log" — but per docs/apply/master/error_handler.md this apply is void on this driver, so the returned string is silently discarded and the comment's assumption doesn't hold (confirmed by reading the driver's own apply doc, not guessed). Added a permanent efun::write_file("/log/RUNTIME_ERRORS", ...) insurance write inside the handler, same pattern already applied on wuhanzhan/archive #58.

Confirmed NOT needed (checked by reading the actual source, not assumed)

Known lpcc-sweep failures NOT fixed (pre-existing content bugs/gaps, not driver-compat)

Triaged the remaining 319 failures (after the fixes above took the sweep from 91.8% to 95.0%) by grouping error messages by shape, per AGENTS.md §6b — none of these are on the registration/boot path (confirmed clean via two full interactive tests) and all are scattered across personal wizard sandbox directories (u/f/fund, u/b/bigcat, u/r/ryn, u/k/konn, u/h/hitler, u/e/een, etc. — 200+ of the 319 failures) or orphaned utility content, not core game infrastructure:

Config notes

config.fluffos adapted from the lib's own config.fs (converted to UTF-8 before any other edit, per AGENTS.md §5). Dropped address server ip/address server port (external intermud-address-resolution service, irrelevant here), binary directory (obsolete, matches #53's finding), swap file and reserved size (both obsolete-key warnings on this driver, same as #53). mudlib directory set to the absolute libs/kxkj1/work path (this driver requires it, unlike the original MudOS-era ./-relative convention). Created work/adm/tmp/, work/binaries/, work/data/ (referenced by config/save-data paths, not guaranteed to exist as empty dirs after RAR extraction) and the sibling log/ directory (per AGENTS.md §6, the driver's log directory resolves relative to CWD, not mudlib root — always launched via cd libs/kxkj1 && driver config.fluffos).

Registration-flow transcript (verified end-to-end, twice)

Read adm/daemons/logind.lpc's full callback chain before scripting the test: logon → get_id → confirm_id → get_name → new_password → confirm_password → get_gender → get_points ×7 → enter_world → press_enter. No hidden pre-id client-version/BIG5 gate (the very first prompt is the real English-id prompt) and, notably, no email-collection step at all (unlike archive #53's copy of this same file, which does prompt for email — confirming again that this is an earlier/different snapshot, not the same file). Point allocation is 8 attributes/160 points average 20 each; only 7 are prompted individually (str,cps,int,cor,con,spi,per) — the 8th (kar) is auto-computed as the exact remainder the instant the per prompt is answered, going straight to enter_world() with no further prompt (identical structure to #53's copy of this same logic, just without the email step).

Run 1 — python3 scripts/mudclient.py 127.0.0.1 40063 --timeout 40 --idle 1.2, one continuous connection, --send sequence: qinfeng (English id) → y (confirm new character) → real Chinese name "秦风" (2 characters) → test1234 (password) → test1234 (confirm) → m (male) → 20×7 (attribute points) → ` (press enter) → look → quit`.

Outcome: id accepted, confirmation accepted, "秦风" (a genuine 2-character Chinese name) accepted by the fixed is_chinese/ check_legal_name, password/confirm/gender/all 7 attribute prompts proceeded correctly, character creation completed, and the character was dropped into the real starting room ("世界的入口" — "World Entrance"), with the room's full Chinese description, exits, an in-game board message, and the MOTD bulletin all rendering correctly. look re-displayed the room correctly; quit produced the expected item-drop message ("你丢下一件布衣。") and a clean goodbye ("欢迎下次再来!你离开 游戏。"). Zero crashes, zero permission-denied errors.

Run 2 (fresh id/name, same driver process, confirming no anti-flood throttle issue — grepped for NewIps/IsTimeAllowed-shaped patterns first and found none in this lib, so no cooldown wait was needed): qinfengb → y → real Chinese name "秦风二" (3 characters) → test5678 → test5678 → f (female) → 20×7 → ` → look → quit`. Identical clean outcome, correctly using female pronoun forms ("妳丢下 一件布衣。"/"妳离开游戏。") this time.

debug.log across both sessions combined: zero occurrences of error/denied/fail/crash/undefined/bad argument/recursion/ access beyond the harmless boot-time compiler warnings (unused local variables, "Unknown #pragma", two "Unknown escape sequence '\<Chinese char>'" warnings from stray backslashes in flavor text — same non-fatal category as the "Illegal character" sweep findings above, just below the severity threshold that would make lpcc treat them as hard failures for those two particular files since they occur inside the write()-adjacent feature/message.lpc/std/bboard.lpc, which DO compile).

lpcc sweep

scripts/lpcc_check.sh libs/kxkj1/config.fluffos libs/kxkj1/work, run twice:

1. First pass (before the sweep-discovered fixes above, but after all proactive pre-boot fixes): total=6323 pass=5804 fail=519 (91.8%). 2. Final pass (after fixing the 187-file inherit-ordering cluster, the 11-file SAVE_EXTENSION typo, and the 3-call-site is_killing bug, all described above): total=6323 pass=6004 fail=319 (95.0%). The remaining 319 failures were re-triaged by error-message shape and confirmed to be exactly the "known, not fixed" categories documented above (reserved-word identifier collisions, a nomask multiple- inheritance diamond conflict, decorative-text escape/concatenation typos, and orphaned network-daemon/admin-command content) — zero new or unexplained failure categories introduced by any fix, and zero failures trace back to the registration/boot path (independently confirmed by the two clean interactive tests above).

Driver process launched via the Bash tool's own run_in_background equivalent (setsid nohup ... & disown), confirmed dead by exact PID before finishing (no broad pkill used).

Re-verification pass: driver rebuild + LPC formatter + WASM build

WASM-enablement pass (loopback-allow / uptime / throttle / admin seed)

Standard pass per AGENTS.md §1.3(b)/(e), §1.5.

Gates patched:

Admin account: id fluffos, pw Mud@2026, name 浮浮, (admin) via adm/etc/wizlist (rewrote LF-only — original CRLF made parsed levels carry \r). Registered through the real flow (id → y → 浮浮 → password ×2 → m → 20×7 attribute points → enter). Verified: relogin shows 目前权限:(admin); update /adm/daemons/logind → 成功. NOTE: relogin flow quirk — after the password an extra empty send is needed before commands dispatch (press-enter step). Save files (untracked, NOT gitignored — orchestrator must add): work/data/user/f/fluffos.o, work/data/login/f/fluffos.o.

Retest: fresh normal registration (ceshier / 秦风癸) end-to-end OK (look/score/quit correct, test saves removed); no new errors in debug.log.

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

此前被错误标记为某个不存在于本项目任何档案的原始压缩包文件名的 duplicate_of;这里的内容其实是完全独立、可游玩的游戏(有自己的 -N 变体编号、自己的端口、自己的 README)——duplicate_of 已清除。

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

原生 driver(端口 40063)跑了一遍超出注册流程的完整游玩。这份档案 是 1995 年创立的老牌台湾 MUD,采用点数分配式的天赋系统(8 项天赋, 共 160 点预算,每项 10-30,逐项手动输入分配),和这批档案里常见的 "随机重掷"式流程不同;连线后有一个固定的"世界的入口"欢迎室,需要 额外输入 down 才会真正进入游戏世界,reconnect 后也会先回到这个 欢迎室,测试时容易漏发一步。

主动检查:adm/daemons/logind.lpc 的 printf("%O\n", ob)(第 395 行)已经被原作者自己注释掉(// printf(...)),不是活跃的 §7.34 bug。没有 §8.9 食物/饮水按错误对象 age 初始化的问题——这份 档案的写法完全不同:食物/饮水在天赋点数分配完成的那一刻就无条件 设成 300/300(user->set("food", 300); user->set("water", 300);), 不依赖任何 age 判断,从架构上就避开了这整类 bug。command_hook (feature/command.lpc,F_COMMAND 宏实际指向的活文件)是干净的 nomask,没有 private;另外三份 command.lpc 拷贝都在巫师私人 目录或其它职业指令目录下,不是同一个 hook。

全树 UTF-8 解码扫描发现 5 个真正的 extensionless GBK 文本残留 (AGENTS.md §4.1 已归档条目的又一实例,这次数量最多): doc/help/main_map2(地图说明)、doc/help/quest(任务系统说 明)、doc/skill/taoist.chun(道士门派介绍)、open/island/room/ board(一段"本区域施工中"的告示文字)、open/main/README(和 main_map2 内容高度重叠的另一份地图说明)——file(1) 把其中三个 误判成"COM executable for DOS"(GBK 双字节序列凑巧撞上了 DOS 可执 行档案的识别特征,这正是 AGENTS.md §4.1 早就警告过的"file(1)的 文字/二进制判断不可靠"的又一次印证),另外两个显示成笼统的 "data"。逐个用 Python 试解码为 GB18030 确认全部是通顺的繁体中文 后,用 iconv 转换安装,人工核对内容语义连贯(quest 文件详细解释 了这份档案自己设计的"套装故事"任务系统概念,main_map2/README 是 两份地图分区负责人名单)。同一次扫描里其余 78 个解码失败的文件全 部确认是真正的二进制内容或个人内容——bin/ 目录下的可执行档案、 .zip/.tgz/.pak/.com/.sys 归档和旧版 DOS 程式、以及压倒性 多数的 u/<巫师>/log(每个巫师自己的私人连线记录,不是游戏内容)。

死亡系统:修复了标准的 §7.68,外加一个此前从未见过的全新变体: open/death/npc/{wgargoyle,bgargoyle}.lpc(白无常/黑无常, DEATHROOM 宏指向的 open/death/gate.lpc 实际摆放着 wgargoyle, bgargoyle 摆在north 方向相邻的 gateway.lpc)都有标准的 if (!ob || !present(ob)) return; 复活软锁死守卫,已按已验证的修 法拆分修复。另外发现两个文件都还有一处独立的、指错文件的 bug (新增 AGENTS.md §7.75):reincarnate() 之后紧跟着调用 DEATHROOM->end_death(ob);——end_death() 是真正执行死亡惩罚(按 角色最高的属性类型扣除相应的战斗经验/技能)的函数,但这个函数实际 定义在 open/death/start.lpc 里,不在 DEATHROOM 宏指向的 gate.lpc 里(gate.lpc 只 inherit ROOM,没有这个函数)。 start.lpc 自己的文件头注释还留着 // Room: /open/death/gate.c 字样,加上它确实还在 open/death/bridge1.lpc 的引用图里,说明这 是一次"gate.lpc 被拆分/改写成新版本,但 end_death() 逻辑忘了一并 搬过去"的历史重构遗留——DEATHROOM->end_death(ob) 因此从创档以来 就一直静默地呼叫一个不存在的函数,没有任何玩家真正为死亡付出过属性 惩罚代价。已改成直接呼叫 "/open/death/start"->end_death(ob),指 向函数真正的定义处。

顺手修复一处确认为原始压缩包本身损坏的乱码字(不是转码流程造成 的——用 Python 直接读取 raw 归档的原始字节核对过):open/death/ gate.lpc 的死亡场景描述里"矗立着一座高大的黑色城楼,钗h亡魂正哭 哭啼啼地列队前进"一句中的"钗h"两个字符明显是数据损坏——本轮会话 里另外七个不同血统的档案(bixiecanyang/fy330/fy2mg/yhyxs/ yanhuangwuhun/syxjl/wmkj)的死亡场景都出现过逐字相同的句子 "许多亡魂正哭哭啼啼地列队前进",凭借这么多独立来源的一致印证,有 足够把握把"钗h"还原成"许多",而不是凭空编造。

现场游玩+死亡+复活验证:注册测试角色(秦山 / id qinshan), 在"中央驿站"探索,list 正确显示商店商品(木头/主大陆地图各 10 文钱)。用 fight(按新手指南建议,避免用 kill 免得"被记恨")攻 击"小麻雀",测试角色全程一拳未中就被打死了(初始攻击力过低导致, 内容/数值现象,不是 bug)。死亡后落到"鬼门关","白无常"在场,没 有主动打断复活序列,等待完整走完后重连(记得先 down 才能看到 真实位置,否则会先回到"世界的入口"欢迎室)确认:角色已经复活、站 在"中央驿站"(REVIVEROOM),可以正常执行游戏内指令(down 被 正确识别为"看不懂啦"的无效指令,证明已经不在欢迎室里),score 显示状态正常——这次的 move() 调用没有重现 wmkj 会话里发现的 那种"静默卡住不返回"的未解异常(AGENTS.md §7.74),成功从鬼门关 移动到了复活室,值得作为一个正面对照记录下来。

quit 正常退出("欢迎下次再来!你离开游戏。"),driver 全程存活未 崩溃。debug.log 全程没有真实的 error:/denied/Bad argument/ Too deep recursion 行。formatter 检查(两个死亡 NPC 文件均已是干 净格式,无需重排版)、git status --short libs/kxkj1/ 复查均确认 改动范围干净——八处改动(两处 §7.68 修复+§7.75 修复、一处乱码字修 复、五处 GBK→UTF-8 转码)是跟踪变更,测试角色的新存档保持未跟踪、 未提交。

更正(2026-08-05):§7.68 复活软锁"修复"已撤销

上面提到的"鬼魂离开/不在场时被永久放弃复活流程"曾被当作 AGENTS.md §7.68 记录的一类 bug 修复(把单次判定改成每 5 秒重试)。经用户指出并 重新审视:这更可能是有意的游戏设计,不是 bug——大多数这类档案里 鬼魂根本无法自行移动,所以"不在场"要么从未真正发生,要么是"离开去 在阴间游荡,想回来时再走回这个房间、流程会通过 init() 重新从头开始" 这种有意为之的宽松机制,而不是需要强制追上玩家的错误。强行重试还可能 引入新问题:如果鬼魂之后又走回这个房间,旧的重试和 init() 重新触发的 新一轮流程可能同时运行,导致对话重叠错乱。已把这处改动撤销,恢复成 原始的 if (!ob || !present(ob)) return; 单次判定写法(bmxkx2001 除外——那份档案里这确实是一个真实存在、经过实际复现验证的 bug:鬼魂 本身完全无法移动,是另一个不相关的 NPC 强行把鬼魂拖走导致的)。详见 AGENTS.md §7.68 顶部的撤销说明。

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

§7.100 sub-threshold instance (2026-08-20)

Found during the §7.100 tail-sweep (below the original 166-lib survey's

=100-occurrence threshold, never checked). 55 live

replace_program(ROOM); occurrences across 55 files: 52 standalone room-file occurrences (open/cold/*.lpc, open/hall/jail/jail4.lpc, u/* wizard-dir rooms) plus 3 string-builder-embedded occurrences in this lib's room-building tool, which is named rmaker.lpc (not roommaker.lpc) with 3 separate copies — obj/rmaker.lpc, u/j/joel/obj/rmaker.lpc, u/a/anmy/obj/rmaker.lpc — all fixed. The 8 files actually named roommaker.lpc in this lib never had the bug (different, unrelated tool). One pre-existing already-//-commented instance (u/i/ice/workroom.lpc) left untouched. A full post-fix grep confirms 0 live occurrences remain. Verified via a clean native driver boot (zero new debug.log errors, port listening, killed by exact PID after ~8s).

``§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 open/death/npc/bgargoyle.lpc, open/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): 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 sweep (2026-09-01): enable_player() reentrancy from init()

Same corpus-wide bug class as mhxy/wuhanzhan (AGENTS.md §7.19), and the same sibling lineage as kxkj/kxkjii2 but a full generation older -- this lib uses open/ (not d/) for its domain/zone directories. 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() chain -- confirmed via a body-aware static scan of every init() in this lib: 6 NPC files under open/gblade/npc/pker{1..5}.lpc (and a 6th sibling) call setup() directly from init(), after create() 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, re-entering the same chain while the original call is still on the stack -- genuine reentrancy, crashing with "Too deep recursion" (most likely on an NPC's first-ever preload/compile).

feature/damage.lpc's revive() calls enable_player() again while the object is still living() -- this lib has no cmds/std/sleep.lpc wakeup mechanism, so revive() is the only confirmed legitimate re-enable path here. This confirms a bare if (living(this_object())) return; guard would be the WRONG fix -- 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 the legitimate revive re-enable unaffected. enable_player() had a single fall-through exit (no early returns, unlike kxkj/kxkjii2's if (!this_object()) return; variant), 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-03,第三轮)

新角度:2026-08-04 第一轮已经走完中央驿站 list、战斗死亡和复活。 本轮只补加入公会 + 拜师,并核对 fy3xd 记下的 cmds/std/save.lpc 影子文件嫌疑。

深度功能测试(§10.7,2026-10-04)— negative range ends

scripts/lpc_fix_negative_ranges.py: 5 line(s) in 2 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-04)— stray backslash before a closing quote

A Big5 character whose second byte is 0x5C was written with one extra backslash after it (the old driver read 5C 5C as one backslash and so completed the character) and the UTF-8 conversion kept it (KB 03 §4.4). Before a closing quote it escapes the quote, the string runs into the next line and the file does not compile. scripts/lpc_fix_big5_quote_backslash.py deletes it when the character before it encodes to cp950 with 0x5C as second byte and the quote ends an expression. Here: open/badman/obj/meal.lpc (餐\), open/badman/npc/pard.lpc (豹\), daemon/class/scholar/obj/secret_book.lpc and u/a/anmy/book/secret_book.lpc (功\ twice each), u/f/fund/mud/cmds/std/enable.lpc. Three of the five load now (HEAD: none); the two books compile and fail only when loaded without a this_player().

深度功能测试(§10.7,2026-10-05)— here-document terminators

scripts/lpc_fix_heredoc_terminator.py --all --apply: 2 here-document block(s) repaired (2 with the terminator glued to the last text line, 0 with it indented), so End of file in text block no longer hides the room or object behind them: open/capital/room/king/kr4-5.lpc, u/a/anmy/room/kr4-5.lpc. The terminator must start its line (the lexer's own test, KB 04 §6.10); a glued one lost its newline in the GBK -> UTF-8 conversion together with a half character, which stays out.

深度功能测试(§10.7,2026-10-04)— paths named in another case

The archive comes from a case-insensitive host: files are stored as BAGUA0.lpc, longjing.C, d/SHAOLIN/, the code names them in lower case (__DIR__ "bagua0", "tea/longjing", "/d/shaolin/..."), so the rooms, NPCs and items behind them could not be loaded (a .C file is not an .lpc file; KB 03 §4.5). scripts/lpc_case_paths.py --convert --apply kxkj1: 6 file(s) renamed to lower case (.C -> .lpc, .H -> .h) and 10 path reference(s) in 9 file(s) rewritten to the new spelling; 0 skipped, 0 ambiguous. Load check of the 18 objects that were renamed, edited or name a renamed path (HEAD against the working tree, an object is the same under any spelling of its path): 12 PASS -> 18 PASS, 0 that loaded before fail now, 6 more load.

6 files moved (6 .lpc); mostly under open/main/room (6). A rescan with scripts/lpc_warnings.py kxkj1 is still due: the renamed files are compiled for the first time.

深度功能测试(§10.7,2026-10-05)— room base survives a raising NPC

scripts/lpc_resilient_room.py --apply: make_inventory() of std/room.lpc loads each inventory object as if (catch(ob = new(file)) || !objectp(ob)) return 0;. new() of a file that is not there returns 0 (the room just lacks that NPC), but new() of a file whose create() raises (a skill file for set_skill() this archive never had, a carry_object() item that is not there, a header that never shipped) raised inside the room and the room did not load at all. The wrong-case renames of this lib (the section above) make the NPCs behind them reachable for the first time, so a room that holds one with such a content gap would have gone from "NPC missing" to "room missing"; now it loads without that NPC, as it did before. The room base compiles and loads with the change (HEAD against the working tree). KB 03 §4.5.

深度功能测试(§10.7,2026-10-05)— tail() simul_efun

scripts/lpc_add_tail.py --apply: cmds/apr/tail.lpc calls tail(file), an efun of the MudOS this archive ran on that FluffOS does not have (Undefined function tail: the command did not compile). adm/simul_efun/file.lpc now defines void tail(string file): the last 10 lines of the file, written to the player. Load check (HEAD against the working tree): 1 of the 1 tail command file(s) failed to load at HEAD, all load now, and the simul_efun file loads. KB 04 §6.2.

深度功能测试(§10.7,2026-10-05)— 房间列出的物件缺档时房间照常加载

房间基类 std/room.lpc: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、多件 OK。

深度功能测试(§10.7,2026-10-07)— 兵器的 actions 函数指针

set("actions", (: WEAPON_D, "query_action" :));:旧 MudOS 把 (: 字符串, "函数" :) 当作 call_other 函数指针,本驱动把它当作表达式函数指针,求值只得到字符串 "query_action"。没有对应兵器技能时 feature/attack.lpc 直接用兵器的 actions,COMBAT_D 拿到的不是 mapping,reset_action() 后仍不是,记一条 bad action 就不出招——拿着这些兵器打不出攻击。改成别的兵器早已用的 (: call_other, WEAPON_D, "query_action" :)(KB 04 §6.10):std/weapon/throwing.lpc、std/weapon/stick.lpc、std/weapon/whip.lpc、std/weapon/sword.lpc、std/weapon/stabber.lpc、std/weapon/axe.lpc、等共 11 个。改动的文件在 HEAD 与工作树分别加载(新进程),无回退。

深度功能测试(§10.7,2026-10-07)— 兵器的 actions 函数指针

open/poison/obj/esword.lpc:(: __FILE__, "query_action" :) 改成 (: call_other, __FILE__, "query_action" :)(与 kxkj 同;__FILE__ 是字符串,本驱动把原写法当作表达式函数指针,KB 04 §6.10)。这个文件第 28 行的名字被编码弄坏,HEAD 起就编译不过。

深度功能测试(§10.7,2026-10-07)— 群发信件没有收信人

obj/mailbox.lpc send <group> <file> <title>:循环里 mail["to", groups[i]]; 是什么也不做的表达式(LDMud 多值 mapping 的写法),每封信都没有 to 字段;改成 mail["to"] = groups[i];。新进程编译通过。

深度功能测试(§10.7,2026-10-07)— 编译警告整理

scripts/lpc_warnings.py kxkj1 --fix 加 scripts/lpc_fix_no_effect.py --apply,共改动 799 个 .lpc 和 1 个 .h(多为删去未用的局部变量)。HEAD 与工作树分别加载(新进程):741 -> 741 通过,无回退;改过的头文件的 135 个包含者 134 -> 134 通过。启动时警告 34 -> 0;新进程登录(新人物确认)正常。

深度功能测试(§10.7,2026-10-11):“无副作用表达式”警告复查(批 4)

深度功能测试(§10.7,2026-10-12):编译警告收尾

可编译文件中的编译警告 95 → 0,不加 pragma,逐条在源头修;可编译文件 6053 → 6061。

发现的真 bug:

其余:

改动的 92 个文件与继承 F_LIQUID、include 改动头文件的对象共 97 个,HEAD 与工作树各载入一次:HEAD PASS 84,tree PASS 92,regress 0,新载入 8(上面的 8 个 NPC);5 个 FAIL 两边相同(u/d/dark/glass、两份 kawali、u/f/fund/test_man、u/o/onion/npc/noname,本身有编译错误)。lpc_audit_removed_locals.py 0 处待看。

NPC 带着本库没有的物品,载入失败(2026-10-15,KB 06 §7.73)

2 个文件、8 处在 create() 里 carry_object("<本库没有的文件>")->wear()(或 wield()、set_amount()):carry_object() 得 0,接着的调用报 Bad argument 1 to EFUN call_other(),NPC 根本载入不了,该有它的房间里就少了这个人。多是从别的系统搬来的 NPC 用了原系统的物品路径(最常见:/daemon/class/bandit/icy_boot、/daemon/class/bandit/icy_girth、/daemon/class/bandit/icy_cloth)。每处改为 { object carried_ob = carry_object(...); if (carried_ob) carried_ob->wear(); }(scripts/lpc_guard_carry_object.py):NPC 照常出现,只是不带这件东西;文件补回来(或是虚拟对象)照样会带上。载入检查:改动的文件改前能载入 0 个,改后 2 个(2 个原来载入不了),没有退步。

set_skill() 遇到本库没有文件的武功不再抛错(2026-10-18,KB 06 §7.256)

feature/skill.lpc 里的 set_skill()、map_skill()、prepare_skill() 碰到没有武功文件的名字就 error("F_SKILL: No such skill (…)"),调用它们的 NPC create() 整个中断:NPC 载入不了,刷出它的房间也少一个人。本库有 1 个对象设了本库没有文件的武功(2 个名字,最多的是 tenderzhi、iceforce)。三处都改成 return:这一门武功不给、不映射,对象照常载入,只是少了它(缺的武功本身仍是内容缺口)。抽样载入这些对象:1 个里 1 个通过。(scripts/lpc_guard_set_skill.py)

全局头文件丢了 1 个宏(2026-10-19,KB 04 §6.16)

/include/globals.h 里没有定义 DEATH_ROOM,用到它们的物件(名单里 1 个)编译时报 Undefined variable/Undefined function,整个物件载入不了(编译器在第一个未定义的名字上停下,后面的错误和警告都看不到)。同系的库在各自的头文件里都有这几行:照其中和本库共有文件最多的那个库,原样补到 /include/globals.h 最后一个 #define 之后,宏体里出现的路径在本库里都存在。补完后名单里有 1 个载入,其余还差别的东西。(scripts/lpc_restore_defines.py)

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 载入失败。文件末尾少了 }(最后一个或两个字节丢了),补上:/u/h/hitler/skill/kang_kee.lpc。修后与 HEAD 逐个对比载入:这 1 个物件全部载入,没有退步(scripts/lpc_restore_from_twin.py、lpc_fix_eaten_quote.py --comma、lpc_fix_eof_braces.py)。

补回标点后新载入的物件里的未使用局部变量(2026-10-19,KB 04 §6.10)

之前载入失败、补回丢失的标点后才载入的物件里还有未使用的局部变量警告,共 1 个文件:/u/h/hitler/skill/kang_kee.lpc。删掉没有用到的声明;用 scripts/lpc_listcheck.sh 对比 HEAD 和改后,物件仍然载入,没有警告。

旧驱动的类型宽松:缺省参数、无类型形参、数组初始化、class 变量(2026-10-19,KB 04 §6.19、§6.20)

原来的 MudOS 把调用少传的参数补 0、把没写类型的形参当 mixed、不检查变量的声明类型与初始值,也允许变量叫 class;这个驱动在编译时全部拒绝,整个物件载入失败。修了 15 个文件:/cmds/adm/addguild.lpc、/cmds/adm/delguild.lpc、/cmds/adm/punlish.lpc、/cmds/adm/unpunlish.lpc、/cmds/std/guild.lpc、/u/a/amrol/master_chen.lpc、/u/a/anmy/cmds/rankd.lpc、/u/f/fund/guild.lpc 等 15 个(scripts/lpc_round_files.py 的修复轮:调用处补写 0、无类型形参补 mixed、string X = ({...}) 补星号、void 函数的返回值,以及 class 变量改名 pick_class)。逐个文件在 HEAD 和改后载入对比:这些文件里 14 个原来载入失败、现在载入,没有退步。

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)。改动:/daemon/class/scholar/six-fingers/handwriting.lpc(1 处)。

行编辑器指令编译失败:(: this_object(), ({ "do_to", me, arg }) :)(2026-10-20,KB 06 §7.284)

Illegal to use local variable in functional.:call_other 形式的函数指针 (: ob, ({ "函数", 参数 }) :) 的数组里只能是常量,写了局部变量 me / arg 整个指令就编译不过,describe / plan / sig / song / to 这类先开编辑器、再回调自己的指令因此从未能用。改成 (: call_other, this_object(), "do_to", me, arg :)(参数在建立指针时绑定,编辑器再把输入的文字接在最后,do_to(me, arg, text) 收到全文;scripts/lpc_fix_functional_locals.py)。改动:/cmds/std/describe.lpc(1 处)、/cmds/std/sig.lpc(1 处)、/cmds/std/song.lpc(1 处)、/cmds/std/to.lpc(1 处)、/cmds/wiz/plan.lpc(1 处)。

登录密码超过 255 字节:crypt() 抛错(2026-10-20,KB 06 §7.294)

驱动的 crypt() 对超过 255 字节的密钥直接报错(Error in crypt(), check your salt),老驱动则按任意长度散列。在登录提示符下输入 256 字节以上的密码,密码检查那一行就抛错,连线停在一个裸的 > 提示符上,登录走不完(password 指令的旧密码检查同样);用 300 个 x 当参数的扫描发现的。/adm/obj/simul_efun.lpc 里补了一个同名的 simul_efun crypt(key, salt):只有超长的密钥才被截短(先截到 255 个字符,再逐字符截到 sizeof(to_buffer(key)) <= 255,限制按字节算,一个汉字占三个字节),再交给 efun::crypt();普通密码原样散列,已存的密码散列不受影响(scripts/lpc_add_sefun.py crypt)。

do 指令编译不过:变量名 in 是保留字(2026-10-20,KB 04 §6.26)

cmds/std/do.lpc 的 parse() 里 int i, in, n;(“在引号里”的标志):in 在这个驱动里是 foreach (x in y) 的关键字,syntax error, unexpected L_IN,do 指令(一行里连发几条命令)从来没有加载过。scripts/lpc_fix_in_ident.py 把变量改名为 in_var(5 处);u/f/fund/mud/cmds/usr/do.lpc 是同一份。加载检查 2/2,HEAD FAIL → tree PASS。

(: 函数 :) 指针指向对象自己没有定义的函数(2026-10-22,KB 06 §7.355)

item_desc / inquiry / chat_msg_combat 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:编译不报错,用到时驱动报 *Undefined lfun pointer called: 函数名(look 某物、ask NPC about 话题 直接出错,战斗 / 闲聊里的指针在 NPC 的 chat() 里出错,这一拍心跳的后半段被跳过)。scripts/lpc_scan_callout_targets.py --kinds=lfun。 还剩 3 个函数没有补(other 3):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/daemon/skill/blackforce.lpc:force_damage、/daemon/skill/shakill.lpc:reversek、/daemon/skill/windforce.lpc:force_damage。

log/ 下的日志子目录没有人建:写日志的 write_file() / log_file() 报错(2026-10-22,KB 06 §7.358)

这个库的代码往 log/ 的 1 个子目录写日志:log/harass(feature/message.lpc)。压缩包、git clone 和站点包里都没有这些目录(本地启动没有写过它们,gen_keep_dirs.py 没记),write_file() 对不存在的目录抛 *Wrong permissions for opening file /log/dlog/money for append. "No such file or directory",调用它的函数在写日志那一行中断,后面的奖励、标志、步骤都没有执行。本库的 log_file() 是 write_file(LOG_DIR + file, text),目录不存在就抛同样的错误(实测)。把 log/harass 记进 scripts/wasm_keep_dirs.txt(scripts/lpc_keep_log_dirs.py;站点和 pristine 树按它建空目录)。证明(scripts/lpcc_eval.py,在 /adm/daemons 这类目录下的求值对象里写 /log/zzdirprobe/...,新进程)见 KB 06 §7.358 的实测表。

(: 函数名 :) 指针指向本库没有的函数:只含这个指针的行加了注释(2026-10-22,KB 06 §7.355 补充)

inquiry / item_desc / chat_msg* 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:用到时(ask、look、NPC 闲聊)驱动抛 *Undefined lfun pointer called: 函数名,这一拍心跳的后半段被跳过。这些函数没有可以补回的来源(别的库同一路径的文件里没有,或者它还要用本库没有的东西),所以 1 个文件里 2 行只含这个指针的行("post_action": (: reversek :),)加了注释,原文保留并写明原因,这一项当作没有这个话题 / 物品 / 闲聊条目(scripts/lpc_fix_dangling_lfun.py;#include 的文件在库里缺失的对象、指针不在整行上的写法没动)。 前提(function_exists())和加载检查(HEAD 与工作区对比,本库改动的 .lpc 文件)的结果见 KB 06 §7.355:没有一个回归。

按字节写的汉字循环、茶馆猜诗和同盟频道标题(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)。本库 汉字循环 / is_chinese 区间 2 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。

Gsword 出口仍指向 /u/b/bigcat(2026-10-23,KB 06 §7.371)

剑客区已在 /open/gsword/,出口与 mob 路径仍写 /u/b/bigcat/…。scripts/lpc_fix_bigcat_gsword.py 在目标存在时改写;无对应文件的 ntree/wtree/etree 出口删除。本库 38 处。证明:kxkjii2 的 forest3 HEAD 北向 /u/b/bigcat/room/forest4,改后 /open/gsword/room/forest4 可加载;tree1 只剩南向回 tree。

/open/ 上残留的条件赋值(2026-10-23,KB 06 §7.290 Also)

3 文件(j3、r5、r7):与 kxkj 同形的 arg = "light"/"water" → ==(§7.290 Also)。

open 下死出口由对侧房间修好(2026-10-27,KB 06 §7.257 Also)

lpc_fix_dead_exits 的 SKIP 曾把 /open/ 当巫师目录。本库本批出口改写见该提交(大小写/错名,由对侧出口回指判定)。证明见 KB。

深度功能测试(2026-10-27,§6.25 #inherit)

u/h/hitler/skill/mndance:#inherit → inherit;招式字符串缺收尾引号与逗号;valid_learn 补 object ob。

深度功能测试(2026-10-27,§6.25 pkroom tell_room 缺房间)

open/gblade/room/PKR/pkroom 的 tell_room(HIY "…") 少了房间参数;改为 tell_room(this_object(), …)。证明:改后加载。

深度功能测试(2026-10-27,§6.25 one-arg message_vision)

message_vision("…") 补第二参(me / TP / this_player())。

深度功能测试(2026-10-27,§6.10 未知 pragma save_binary/optimize)

删除本库中 FluffOS 不认的 #pragma save_binary / #pragma optimize… 行。