info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
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
内容亮点
- 与"新狂想空间II"不同,本版没有邮箱注册这一步,注册流程更简洁。
- 更正(2026-08-05):上面提到的"7.68 复活软锁"修复已经撤销——经重新评估,鬼魂"不在场"时放弃复活流程更可能是有意的游戏设计(多数这类档案里鬼魂本身就无法自行移动,离开是一种游荡机制,回来时 init() 会重新触发流程),不是需要强制重试的 bug;详见 NOTES.md。
深度功能测试新发现的 bug(§10.7,2026-08-04)
- §7.68 复活软锁死(第 10 例):
open/death/npc/{wgargoyle, bgargoyle}.lpc(鬼门关的白无常/黑无常)的复活流程在角色暂时不在 场时会直接return,永久放弃复活。已按标准修法拆分为"重试"与 "放弃"两种情况。 - §7.75(新增条目):
end_death()指错文件,死亡惩罚从未真正执 行过:上述两个文件复活完成后调用的DEATHROOM->end_death(ob)实际指向open/death/gate.lpc,但真正的死亡惩罚逻辑定义在open/death/start.lpc(该文件自己的头注释还留着// Room: /open/death/gate.c,加上确认它仍被bridge1.lpc引 用,判断这是一次文件拆分/重构时遗漏搬迁的历史遗留 bug)。已修正为 直接调用start.lpc。 - §4.1(第 4 个确认实例):全树 UTF-8 解码扫描发现 5 个 extensionless 的 GBK 文本残留(
doc/help/main_map2、doc/help/quest、doc/skill/taoist.chun、open/island/room/ board、open/main/README),已转换为 UTF-8。 - 顺手修复
open/death/gate.lpc场景描述中一处确认为原始压缩包本 身损坏的乱码字("钗h" → "许多",凭本项目内另外 7 个不同血统档案 中逐字相同句子的印证)。 - 现场验证:注册 → 商店 → 战斗死亡 → 鬼门关 → 未被打断的完整复活 → 重连确认落地"中央驿站"且状态正常,全程
debug.log干净。
在线试玩
https://mudlibs.fluffos.info/kxkj1/
管理员账号 / Admin account
- id:
fluffos - 密码 / password:
Mud@2026 - 中文名 / display name: 浮浮
- 权限 / level:
(admin)— 最高权限。 - 授权方式:
work/adm/etc/wizlist加入fluffos (admin)。
警告:正式对外开放前请务必修改此密码。
本地运行
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:
- Archive file sizes differ:
archives/狂想空间.raris 3,710,123 bytes;archives/新狂想空间II.raris 5,590,619 bytes. Not byte-identical (unlike the genuine狂想空间.rar/狂想空间 (1).rarduplicate pair already in AGENTS.md's Duplicate archives table — confirmed those two ARE identical, this archive is the "keep" side of that pair and was the only one processed here). - Raw file counts differ substantially: this archive extracts to 7,947 files (root dir named
ofs/); archive #53's raw tree has 14,440 files (root dirfsII/). Archive #53's raw tree has three extra top-level directories this one lacks entirely (d/,nets/,player/). - Core files differ in size AND md5, with earlier timestamps:
- 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.
- Same lineage, same collector-site distribution, same admin account, but an earlier/different revision: both archives'
master.cshare the exact same header comment (// for ES II mudlib / original from Lil / rewritten by Annihilator (11/07/94)), confirming the same ES II mudlib base already seen acrosses1_win/esI/xkx2001/rzrmud/bmxkx2001/wuhanzhan/haiyang2/yanhuangwuhun/kxkjitself. Both archives'小熊泥苑.txtreadme (the archiving/collector site,http://dtxy.126.com) carries the exact same claim — this archive's copy: "97年就开始玩狂想...我申明我的狂想源 码不是从老jack手上偷出来的, 是自已把台湾版狂想空间big5转成gb码提供下载 的" ("I didn't steal this from old Jack, I converted the Taiwan version of 狂想空间 from BIG5 to GB myself") — same collector, same claimed Taiwan-BIG5-to-GB conversion story as #53's own collector-site readme. Both archives' wizlist/config reference the same admin accountbear(this archive'sadm/etc/wizlist:bear (admin); #53's credit line namedbear/wadeas manager). This archive ALSO carries an extra readme #53 doesn't have,新改动(一定要看).txt("New changes, must read"), dated Dec 7 2002 by a wizard named "玩具熊" (Toy Bear), describing a bug-fix pass ("主要是解决了不能正常注册和进入及提升权限 的问题" — "mainly fixed the can't-register/can't-login/can't-elevate- permissions issues") and providing test accounts (bear/123456wizard,ronger/123456player) — i.e. this archive is a separately circulated bugfix snapshot of the same underlying game, not the same file redistributed. - Conclusion: this is a genuinely distinct codebase snapshot/fork — same game, same ES II base, same distribution lineage/collector site, same
bearadmin account, but a different (and by every file timestamp, earlier) development snapshot with substantially different file counts and file contents in every core admin file checked (master/logind/securityd differ in both size and md5; only the tiny chinese.c is near-identical, and even that has one cast-related diff). Processed as its own lib, per the task's explicit instructions, porting archive #53's proven fixes directly wherever the same bug shape was confirmed present (§15h, §15t's three include-resolution bugs, then_area.h/cold.h/basic_skill.lpcprecedents all recurred here almost verbatim — see below).
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)
- §4 (
load_object-in-valid_read/valid_writerecursion):master.lpc'svalid_write/valid_readonly ever callfind_object (SECURITY_D)(neverload_object), degrading to deny/allow respectively if not found — no lazy-load-during-compile pattern exists at all here, so no recursion risk regardless ofcatch()— this is actually a SIMPLER (safer) shape than #53'smaster.lpc, which DID have (and needed guarding on) a lazyload_object(SECURITY_D)call in the same applies. - §7 (
get_root_uid/get_bb_uid): both already implemented directly inmaster.lpc, returningROOT_UID/BACKBONE_UID. - §14 (2-arg
valid_override):master.lpc'svalid_override(file, name)IS 2-arg, but its final fallthrough is an unconditionalreturn 1(onlymove_object/destructoutsideF_MOVEare ever denied) — every#included simul_efun-fragmentefun::override is allowed by the same permissive default that would apply to the 3-arg case anyway; confirmed via a clean boot + full lpcc sweep with zerovalid_override-related denials anywhere indebug.log/lpcc_fail.log. - §15n (custom
securityd.lpcblocking compile-time reads): this lib'svalid_readhas the SAFE shape already — its very first substantive check isif (func != "read_file" && func != "file_size" && func != "stat" && func != "read_bytes" && func != "tail" && func != "ed_start") return 1;, meaning"load_object"/"recompile_object"/"include"(none of which are in that exclusion list) are allowed UNCONDITIONALLY before the ACL tables are ever consulted — the ACL (exclude_read/trusted_read) only ever gates genuine DATA reads, not compile-time file access. Confirmed by reading the function in full; no fix needed (this is actually a more robust default than several other libs in this family that needed §15n's explicitswitch(func)early-allow patched in). - §15s/§15aa (
message()/tell_room()wrapper passing a bareint 0exclude argument, or a same-named wrapper miscompiling to the real efun):adm/simul_efun/message.lpc'stell_room(ob, str)(2-arg form) does pass its unsetobject *excludevarargs parameter (defaulting to0) straight through to the realmessage()efun's 4th argument, the same shape §15s originally found broken onyueyingqiyuan. But reading this driver's actualf_message()implementation (~/src/fluffos/src/packages/core/efuns_main.cc) shows the 4th-arg handling already gracefully degrades ANY non-object/non-array value (including a bareT_NUMBER0) toavoid = &the_null_array— nobad_argument()call for that argument at all. No fix needed; verified empirically too, since this file'stell_room()fires on every room's ordinary broadcast throughout both full interactive test sessions with zerodebug.logerrors. (§15aa's self-name-shadowing risk doesn't apply either — this file never defines its ownmessage()override at all, so everymessage(...)call inside it binds straight to the real efun as intended, no forward-declaration ordering issue possible.) - §15l (
master.lpc create()destructing/reloadingSIMUL_EFUN_OB): grepped fordestruct/efun::destructtargetingSIMUL_EFUN_OB/MASTER_OBinmaster.lpc— none present. - §15x (hardcoded
MUD_PORTmismatch):master.lpc'sconnect()apply takes no arguments and does no port comparison at all; greppedinclude//adm/forMUD_PORT/PORTNO-shaped constants — the only hit is an unrelated driver-side config-key name string inside a comment ininclude/runtime_config.h, not a mudlib-side dispatch gate. Confirmed empirically too: both interactive test connections succeeded on port 40063 with no rejection. - §8e (
tail()fake efun): zeroefun::tail/baretail(call sites anywhere inadm/simul_efun. - §15f (bare
arraydeclarations): zero matches for thearray name;/array name = expr;shape. - §8f (
TYPE * a, b;forgotten-star bug): 214 instances of theTYPE *name1, name2comma-list shape found via grep; spot-checked several (string *k, list=""instd/room/shop.lpc,object *enemy,targetinopen/japan/npc/master.lpc) and confirmed each is intentionally mixed (the starred variable is genuinely used as an array, the bare one genuinely assigned a scalar a few lines later) — same conclusion as archive #53's identical check on this same lineage. No fix applied. - §15u (dormant phone-home/license-check deletion trap): grepped
securityd.lpc/master.lpcfor mass-deletion orshutdown()gated on an opaque check — nothing resembling this pattern found. - Encoding stragglers:
convert_lib.shreported only 1 lossy file (data/emoted.o, a save-data file — same category of acceptable minor loss on seed/example data documented for every prior lib in this family). A follow-upfile-classifier sweep for the known "misclassified as data" false-positive pattern (§1) found no additional stragglers.
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:
- ~150 files, "Illegal character 0xNN" spanning many distinct shapes (spot-checked ~10 to confirm variety before deciding NOT to risk a blanket regex fix, matching archives #53/#63's own precedent for this exact category): a stray backslash immediately before a fullwidth Chinese punctuation mark inside a string literal (e.g.
"...大餐\,不知 道..."— the lexer treats\as starting an escape sequence, then chokes on the following multi-byte UTF-8 character's raw bytes one at a time), missing+concatenation between ANSI-color macros and adjacent quoted text (same shape as #53's own "known, not fixed" category), a literal terminal escape sequence ([D[D[D[2~) accidentally typed into aset_name()call, and a handful of genuinely malformed quote/escape sequences in flavor text. All decorative/flavor content (item descriptions, skill names, NPC dialogue), never touched by registration. - 34 files, "unexpected L_CLASS": source using the bare identifier
classas a variable/parameter name (string class="",receive_message(string class, string msg)) —classis a reserved word in this driver's grammar (used for LPC struct-styleclassdeclarations), a genuine pre-existing authoring collision, not something this conversion introduced. Scattered across personal wizard directories (u/w/wade,u/a/anmy,bin/), none reachable from the registration/boot path.
- 27 files, "Illegal LHS": source using the bare identifier
newas a variable name (new = allocate_mapping(3); new["name"] = ...) —newis a reserved keyword (object-instantiation efun) on this driver, same "identifier collides with a reserved word" root cause as theclasscategory above, just a different keyword.open/poison/room/ r1.lpc/r2.lpc(a small, isolated quest room pair) account for a chunk of these; the rest are scattered personal-directory files. - ~39 files, "Illegal to redefine 'nomask' function" (
_set/_query/_delete/set_path/query_busy/is_busy/command_hook): a real multiple-inheritance diamond conflict (two inherited bases both declaring the samenomaskfunction name) in a scattered set of personal-wizard/orphaned NPC files (open/capital/npc/solder_officer, severalu/f/fund/*files,u/o/oda/npc/boss4,u/o/onion/npc/vendor,u/w/wade/room/casino) — not a shared single root cause fixable in one shot (each file's own specific pair of conflicting inherits differs), and none are on the registration/boot path. - 18 files, "Undefined variable 'SAVE_EXTENSION'": already fixed, see item 7 above — this count is the PRE-fix number, included here only for completeness of the "before" triage; zero remain after the fix.
- **~9 files,
adm/daemons/network/*** (ms,userid,pingtcp,name_server,mail_serv,netmail,telnetd,pingd,inetd): orphaned network utility daemons, none present inadm/etc/preload, same category as AGENTS.md §12/§13's documented orphaned-content pattern — not fixed, never reached by any live code path. - **~8 files,
cmds/std/*** (guild, a "复件 help" backup-copy file,to,unwieldd,sig,do,describe,song): ordinary in-game admin/player commands with their own pre-existing typos/bugs, not on the registration path (confirmed via the clean interactive test), left as-is per AGENTS.md's "prioritize breadth over depth" guidance.
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
- LPC formatter: ran
format-corpus.mjsover all 6,323.lpcfiles — 6,279 reformatted in place, 25 already-idempotent, 19 refused (nonzeroerrorsexpected/fine per the tool's own contract). - Native retest against rebuilt driver (
~/src/fluffos/build-debug/ src/driver, freshly rebuilt from upstream master): booted clean, zero fatal errors (only routine compile warnings). Full registration re-verified with a fresh real name (秦风辰) via the documented flow (id → confirm → Chinese name → password ×2 → gender → 7×attribute points → enter world);look/score/quitall produce correct dynamic output, arriving at 世界的入口 as before. No regressions from the rebuilt driver or the reformat pass; nothing to fix. - WASM build test (
scripts/wasm_client.jsagainstbuild-wasm/src): boots cleanly in-process, only ordinary compile warnings. Full registration/login flow completed successfully under WASM too (fresh name 秦风己, same attribute-point flow as native),look/quitalso correct, MOTD/board rendering identically to the native run — this lib has no IP/site-gating daemon on its login path, so it is not affected by the documentedquery_ip_number()WASM limitation and is fully playable under WASM.
WASM-enablement pass (loopback-allow / uptime / throttle / admin seed)
Standard pass per AGENTS.md §1.3(b)/(e), §1.5.
Gates patched:
adm/daemons/logind.lpcget_id()(~line 164): thebanned_ipprefix-match gate (strsrch on query_ip_number) is now skipped for strict loopback only. (The big multi-login block below it was already commented out upstream.)adm/daemons/securityd.lpcmatch_wiz_site()(~line 95): strict loopback always matches (wizard per-site login restriction).- Uptime startup gate: none (natured.lpc's
uptime() > 72000is an in-game auto-reboot content timer, kept). - Anti-flood throttle: none live (multi-login check commented out upstream).
- Fail-closed correction (retrofit): both gates above initially treated a malformed/non-string IP as loopback (per the original pre-driver-fix instructions). Since
query_ip_number()is now fixed upstream, tightened to strict127.0.0.1/localhost/::1/127.*matching only — a malformed IP now falls through to the original gate logic instead of being waved through.
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 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 7 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
§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 影子文件嫌疑。
cmds/std/save.lpc不是 fy3xd 那种影子文件:这份有完整main()(含save -1/-2备份档)。冷启动后第一次save回 「档案储存完毕。」「备份资料 ok.」。COMMAND_D虽也是while (i--)从后往前扫,但这里没有第二份无main()的/cmds/usr/save挡路。- 加入剑士公会 + 仙剑派拜师(通过):
goto /open/gsword/room/swordhouse(五岳剑盟),柳毅在场,join→「欢迎浮浮加入剑士公会!!」(class=swordsman)。goto /open/gsword/room/g5-1(凌霄宝殿)apprentice teng, 郑士欣不直接收新手,改为select 梁发。goto /open/gsword/room/g2-17apprentice fa→ 「恭喜您成为仙剑派的第五代弟子。」score显示「仙剑派第五代弟子」 「师父:梁发」。冷启动重连后score仍在,save/quit干净。 - 一次脚本会话里
save之后驱动空转:第一次脚本在apprentice之后立刻save,客户端 0.6s 无回音就断开(没quit)。随后驱动 占 50–72% CPU、新连线收不到 banner,直到对本会话 PID 发 TERM。 冷启动后同一账号再save立刻成功,备份档data/backup/user/f/fluffos.o也从 0 字节变成正常大小。没有第二次 复现,不当成已确认的编程 bug,只记现象:断线发生在save的备份cp路径上时,驱动可能停在单线程 eval 里。 - 日志:live
debug.log为libs/kxkj1/log/debug.log。本轮无error:/Too deep recursion。work/log/log只有编译警告。 - 结论:剑士公会
join+ 仙剑派梁发拜师跨冷启动仍在;save指令本身可用。未改代码。
深度功能测试(§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;新进程登录(新人物确认)正常。
- 2026-10-10:编译警告第二轮(按驱动报告逐条修):按位 & 改逻辑运算 1 处,返回类型/原型 1 处,NPC+F_UNIQUE 的 init() 0 个,带初始化的未用局部变量 6 个,只在 #if 分支用的声明移进分支 1 个文件;改动 6 个文件,HEAD 与工作树各载入一次无回退(6 objects; HEAD PASS 5, tree PASS 5; regress 0; newly loading 0),这些文件的警告 8 -> 0。
深度功能测试(§10.7,2026-10-11):“无副作用表达式”警告复查(批 4)
daemon/class/officer/cmds/powerup.lpc:count + count / 2;结果被丢弃,官职战力少算三分之一;改为count += count / 2;。u/下 11 把武器set("actions", (: __FILE__, "query_action" :))是表达式函数(逗号表达式),求值得到字符串,持有者从不出招;改为(: call_other, __FILE__, "query_action" :)(KB 04)。u/j/joel/mail.lpc:mail["to", groups[i]];改为mail["to"] = groups[i];。u/m/mtl/obj/car.lpc:删去空的if (arg == "car") {}。u/t/tide/npc/girl.lpc:P == 0;改为P = 0;。- 改动的对象 HEAD 与工作区都能载入,无回退。
深度功能测试(§10.7,2026-10-12):编译警告收尾
可编译文件中的编译警告 95 → 0,不加 pragma,逐条在源头修;可编译文件 6053 → 6061。
发现的真 bug:
feature/vendor.lpc自己inherit NPC;,而open/capital/npc/solder_officer.lpc、u/f/fund/{killer,officer,sword_man,waiter}.lpc、u/f/fund/room/npc/keeper.lpc、u/o/oda/npc/boss4.lpc、u/o/onion/npc/vendor.lpc在它前面又inherit NPC;:驱动报Illegal to redefine 'nomask' function '_set',这 8 个 NPC 从来载不进来。删去叶子那行后都能载入。- 20 个 NPC 的
chat_msg里写(: "random_move" :):这是返回字符串的函数,不是调用,这些蛇、狼、刀客、游客从不走动;改为(: random_move :)。open/poison/npc/bigsnake.lpc、snakeking.lpc的(: "special_att" :)同样从未执行;改成真指针后special_att()本身也坏:把query_enemy()(整个敌人数组)当成一个对象传给tell_room(),会在每次战斗喊话时报错;改为从敌人里随机咬一个,tell_object()给他,中毒照旧。同类的(: this_object(), "special_att" :)写法(不报警告,open/poison/npc/snake.lpc等十几个文件)仍未修,留待以后。 feature/liquid.lpc的long()最后一档写成第二个amount > max / 2,永远进不去:容器里剩不到三分之一时不显示内容;改为else(“里面装了少许的…”)。u/f/fund/mud/cmds/usr/dumpquest.lpc:printf的%d在任务数为奇数时收到"",改为%s+sprintf("%d", …)。
其余:
- 35 处冗余继承删去(上面 8 处之外多为
inherit F_CLEAN_UP;);u/f/fund/party_npc.lpc被 include 在inherit NPC;前面,自带的inherit F_CLEAN_UP;/inherit F_DAMAGE;与 NPC 重复,删去;u/f/fund/test_man.lpc经 include 的feature/call_soldier.lpc已有inherit NPC;,删去自己那行(该文件另有错误,仍载不进)。 ITEM+F_LIQUID的 18 个容器long()两份:照驱动原来的选择写出liquid::long(raw)。daemon/skill/gsword.lpc、gwhip.lpc的string skill_improved(string me)改为基类的void skill_improved(object me);open/gblade/npc/girl.lpc、open/start/npc/b_guard.lpc的greeting()、u/a/anthony/npc/horse.lpc的die()改void(都由 call_out 或战斗调用,无人读返回值;horse 的善后读的my_boss全库无人设置,照旧不生效)。open/capital/npc/g1.lpc自己的object leader(临时存同伴)与feature/team.lpc的队长leader本是两个变量:叶子改名helper(nosave);open/gblade/npc/pker5.lpc从未使用的全局object enemy(heart_beat()用自己的局部变量)删去。- 6 个港口房间调用定义在后面的
do_start_ship():加原型。u/m/mtl/killer/yar.lpc的本地SKILL_D前加#undef;u/s/server/olddata/kontop2.lpc多余的;;include/net/ftpdsupp.h只在#ifdef GUEST_WIZARD_FTP里用的file移进该分支。
改动的 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 处待看。
- 2026-10-14:新驱动(FluffOS 970d9f09)报
Float value truncated to int(#1426)。46 个文件 103 处:赋值、初始化、return 改写成to_int(...)(值不变,只是写明截断);x op= 浮点先把浮点转成整数再运算(系数小于 1 时 x 直接变 0),改为x = to_int(x op ...):/adm/daemons/combatd.lpc(damage *=)、/u/b/borstquc/combatd.lpc(damage *=)、/u/k/konn/work/combatd.lpc(damage *=)。改动的对象新进程各载入一次,无回退(scripts/lpc_fix_float_trunc.py,KB 04 §6.10)。
- 2026-10-14:1 个文件因
Type of returned value doesn't match function return type ( int vs void )整份不编译:声明为void(或没写类型)的函数却返回值,旧驱动照样把值交给调用者。调用者要用返回值的(add_action 处理函数、命令、辅助函数)改为它实际返回的类型:attempt_apprentice()。新进程比对 HEAD 与工作树:1 个对象,新增载入 0,回退 0(scripts/lpc_fix_void_return.py,KB 04 §6.3)。
- 2026-10-14(补):上面改成有返回值的函数里残留的空
return;改为return 0;(值不变,消除Non-void functions must return a value)。
- 2026-10-14:1 个文件用了颜色宏(
HIW、NOR)却没有#include <ansi.h>(首个错误syntax error, unexpected L_STRING);开头补上;5 个文件的函数声明为int(或void)却返回字符串、对象(int query_seal() { return "…"; }),旧驱动照样把值交给调用者;改为实际返回的类型(scripts/lpc_fix_void_return.py)(KB 04 §6.1、§6.3)。新进程比对 HEAD 与工作树:6 个对象,新增载入 1,回退 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… 行。