info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
属于 ES II(Eastern Stories II)引擎系列武侠 mudlib,与本项目中的 wuhanzhan《大话西游》、wmkj《未明空间》等同属一个大家族,但代码库本身是独立分支,由作者 "hxsd" 开发,以帮派经营和 NPC 招募为核心特色,还内置了一套相当完整的商人/贸易子系统(作者自称"和大航海时代差不多")。游戏世界以中州、少林、全真等门派/城镇为骨架展开,新玩家从"英豪酒楼"起步,可以习武、闯荡江湖、加入帮派赚取产业收入;原始服务器因人气不足与内部巫师团队矛盾而停运,此后作者公开发布了源码,这份归档正是那次公开发布的产物。
English
A wuxia mudlib built on the ES II (Eastern Stories II) engine, part of the same family as this archive's Wuhanzhan (A Chinese Odyssey) and Weiming Kongjian, though it is an independently developed branch. Created by the author "hxsd," it centers on sect management and NPC recruitment, backed by an unusually complete merchant/trading subsystem the author likened to Uncharted Waters. New players start at the Hero's Tavern and can train in martial arts, roam the jianghu, and join a sect to earn income from its holdings. The original server closed after its popularity waned and its wizard staff fell into internal conflict, after which the author released the source code — this archive preserves that release.
README
在线试玩
https://mudlibs.fluffos.info/tiexuejianghu/
管理员账号 / Admin account
- ID:
fluffos - 密码 / Password:
Mud@2026 - 中文名 / Display name: 浮浮
- 权限 / Level: 天神
(admin)—— 本 lib 的最高等级,拥有完整 巫师权限。 - 授权方式:
adm/etc/wizlist。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。
本地运行
cd libs/tiexuejianghu
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40087。
NOTES · 移植与修复记录
tiexuejianghu — 铁血江湖 (Tie Xue Jiang Hu / "Bloody Jianghu")
Archive: archives/铁血江湖.rar (archive #95). Extracted mudlib root:
raw/txjh/export/mudlib/ (the archive nests txjh/export/mudlib/ — a
config.cfg sits at raw/txjh/, one level above the export/ dir it
points into). Port: 40087. Status: done (boots clean, full
registration flow verified three times with real Chinese names, post-login
look/score verified working every time, zero runtime errors in
debug.log across all sessions).
What this is / lineage
The raw config.cfg's own name field (GBK-decoded) is 风云三(本地)
("Fengyun III (local)") — a stale copy-paste leftover unrelated to this
game, the same pattern already seen on dtsl2 (archive
#71-ish). raw/txjh/readme.txt (by the original author, "hxsd") and
raw/txjh/小熊泥苑.txt (the "小熊泥苑"/Xiongxiong-Niyuan mud-resource site's
own re-packaging note) both independently confirm the real game is
铁血江湖 ("Tie Xue Jiang Hu"): a guild-focused wuxia mud with an
unusually developed NPC-recruitment/guild-income system and a full
merchant/trade subsystem ("和大航海时代差不多" — "similar to Uncharted
Waters/Age of Discovery"). The readme states the original server shut down
due to low player counts and internal wiz-team conflict, and the archive
was released publicly afterward. config.fluffos's name field here is
set to 铁血江湖, not the stale 风云三(本地) value.
adm/obj/master.lpc's own header comment says "for ES II mudlib,
original from Lil, rewritten by Annihilator (11/07/94)" — this is the
same "ES II" (Eastern Stories II) lineage shared by the large majority of
already-processed archives (shzs, wuhanzhan, huoying,
yueyingqiyuan, haiyang2, yanhuangwuhun, etc.) — directory layout
(adm/, feature/, std/, obj/, cmds/, d/, u/), securityd.lpc's
ACL shape, and feature/dbase.lpc's real (non-simul_efun) set/query
implementation all match that family, NOT the "nitan"/Lonely lineage
(§15's dbase architecture bug doesn't apply here) and NOT the
TMI-2/ES2/Falcon "XO" lineage. Did not force a match to any specific
already-shipped sibling archive — no byte-identical core files were found
against the handful of siblings spot-checked (master.lpc,
chinese.lpc) — this looks like a genuinely distinct ES II-derived
codebase, not a rebrand of one already in the project.
Fixes applied (with why)
§15h — is_chinese() GBK byte-range check (adm/simul_efun/chinese.lpc)
Was strlen(str)>=2 && str[0] > 160 && str[0] < 255 (a GBK lead-byte
range check assuming byte-indexed strings). On this driver str[i] is a
Unicode codepoint and strlen() counts characters. Fixed to
strlen(str)>=1 && str[0] >= 0x4e00 && str[0] <= 0x9fff (CJK Unified
Ideographs range, >=1 since one character is now one index). Without
this, no real Chinese name could ever pass registration.
§15h — check_legal_name() bound + sliding-window (adm/daemons/logind.lpc)
Same file also implements the name-length/window checks directly (no
separate named.lpc in this lib). Byte-length bound `strlen(name) < 4 ||
8 (2–4 GBK chars) halved to < 2 || > 4` (character count). Thei%2==0 && !is_chinese(name[i..<0]) sliding-window guard (was landing on
alternating *byte* offsets to catch each GBK character's lead byte) had
the i%2==0 && dropped entirely, since every index is already one
character now.
§15ae — private nomask command-hook (feature/command.lpc)
command_hook(string arg) was declared private nomask and dispatched
via add_action("command_hook", "", 1) in enable_player(). This driver
treats private as hidden from add_action's external dispatch (unlike
the original target driver), so every post-login command would have
silently done nothing with zero error anywhere. Dropped private, kept
nomask. Checked and confirmed present exactly as documented in the
catalog — this lib would have failed the exact same silent-command
symptom as xuanjianlu/bmxkx2001/bxsj/bxsj1/xiakexing3
had this not been caught proactively before first boot.
§15ar-adjacent — checked, NOT needed (worth documenting explicitly)
There is no separate commandd.lpc-style command-directory indexer in
this lib matching the catalog's exact sscanf(name+"$", "%s.c$", name)
shape — adm/daemons/cmd_d.lpc's rehash() uses
sscanf(cmds[i], "%s.c", cmds[i]) (a quoted string ending in .c",
not .c$"), so convert_lib.sh's standard quoted-".c"-reference
fixer (§2) already turned it into "%s.lpc" automatically during the
mechanical conversion pass — confirmed by reading cmd_d.lpc post-convert
and re-testing look/score end-to-end. Documenting this because it's
the same *category* of bug as §15ar but this lib's specific text shape
happened to be inside the standard fixer's blast radius, unlike
jinyongwenzi's %s.c$ shape which needed a manual fix. Worth
double-checking on every future lib: same underlying pattern, but only
sometimes auto-fixed depending on the exact quoting.
§15p — excluded dns_master from preload (adm/etc/preload)
Standing policy, applied proactively before first boot.
Non-standard: excluded ftpd from preload too (adm/etc/preload)
adm/daemons/ftpd.lpc (preloaded in the raw archive) #include <flock.h>,
which does not exist anywhere in this archive (only <net/ftpd.h>,
<net/ftpdconf.h>, <net/ftpdsupp.h> exist) — FLOCK_D isn't even
#defined anywhere either, confirming the whole file-locking subsystem
this daemon depends on was never actually wired up in this specific
archive (present as real files in es1_win/esI, absent here). Since
ftpd would be a fatal preload-time compile error and nothing in the
core registration/gameplay path (master/securityd/logind/
simul_efun/command/chinesed) references FTPD_D, excluded it from
preload — the same "trim non-essential network daemon" treatment §15p
already applies to dns_master. Confirmed via lpcc that
adm/obj/master (which pulls in the whole real preload chain) compiles
clean with ftpd excluded.
§14 — valid_override() 3-arg upgrade (adm/obj/master.lpc)
Added the main_file 3rd parameter and check, cheap/free fix per the
catalog, applied proactively. As documented, never actually observed to
matter on a real boot here either (only would affect an lpcc-standalone
compile of an #included simul_efun fragment).
§8g — one shared root cause spanning many "Undefined variable"/syntax errors (include/armor.h, include/globals.h)
armor.hhadTYPE_SURCOAT/TYPE_WAIST/TYPE_WRISTS/TYPE_SHIELDAND their path-macro counterpartsSURCOAT/WAIST/WRISTS/SHIELDall commented out (pre-existing in the raw archive, not conversion fallout) whilestd/armor/{surcoat,waist,wrists,shield}.lpcandd/obj/inherit/armor/*still referenced them unconditionally (8+16 lpcc-sweep failures). Confirmed real callers exist (14/10/5/5 files respectivelyinheritthe path macros) — uncommented all 8 defines.globals.hwas simply missingF_SSERVERentirely (every ES II sibling lib in this project defines it, pointing at/feature/sserver.lpc— but THIS archive's real file lives at/std/sserver.lpcinstead). Added#define F_SSERVER "/std/sserver.lpc"pointing at the file that actually exists here (16 skill filesinherit F_SSERVER).std/skill.lpc(the real target of theSKILLmacro) was a genuinely older revision ofd/obj/inherit/skill/skill.lpc— a byte-for-byte diff showed thed/obj/inheritcopy has 25 extra lines (sum()+NewRandom(), a shaolin-wugong damage-roll helper) that were added later but never synced back tostd/skill.lpc, the file theSKILLmacro (and therefore every skill file) actually inherits. Ported the two missing functions intostd/skill.lpcverbatim. Fixed 21NewRandom-undefined failures plus their cascadingBad type of indexerrors in one shot (all ind/quanzhen/skill/*,d/chengdu/skill/*,d/heimuya/npc/obj/pixie-jian,daemon/skill/old/*).
§12-style orphaned non-LPC content (d/sandboy/map.lpc)
A pure box-drawing ASCII-art room map, not a single line of LPC, caught by
the blanket .c→.lpc rename. Confirmed nothing else references it
(grep -rl for the basename comes up empty besides itself). Renamed to
.txt.
Missing-quote typo (d/obj/books-nonskill/hmeng014.lpc)
string name = "《红楼梦》第十四回; — missing closing " before the ;,
confirmed present in the raw pre-conversion GBK bytes too (not a
conversion artifact). This desynced the parser for the rest of the file,
producing a cascading "unexpected L_NUMBER" + three "Illegal character"
errors on later, perfectly valid UTF-8 bytes. Added the missing quote.
Malformed array literal, genuine pre-existing GB18030 corruption (3 copies of gengfu.lpc: d/jinling/npc/, d/suzhou/npc/, d/suzhou/qinyun/npc/)
nosave string *sym_dee = ({ ...,"酉","","亥" }); (or "酉",","亥"
depending on which lossy-conversion pass) — the raw archive's GB18030
bytes for "戌" (5th of the 10 Earthly Branches, between 酉 and 亥) contain
a genuinely invalid byte sequence (confirmed: primary iconv -f GB18030
fails outright with "illegal input sequence" at that exact position on
all 3 raw copies), so convert_lib.sh's -c-fallback lossy conversion
dropped it, per the Encoding section's documented "iconv -c can eat an
adjacent real byte too" gotcha. Restored the correct sequence
"酉","戌","亥" (the 10 Earthly Branches in their canonical order) by
inference from the surrounding array, not fabricated from nothing.
§15t variant 3 — inherit after global-variable declarations (8 files)
obj/mknpc.lpc, d/suzhou/obj/shoulei.lpc, d/suzhou/npc/guan_jia.lpc,
d/suzhou/npc/test.lpc, d/suzhou/npc/wutiande.lpc, u/oldsix/mknpc.lpc,
u/oldsix/hammer.lpc, u/oldsix/cloth.lpc — all had a mapping/string
* global variable declared textually before their inherit statement,
fatal here ("Illegal to inherit after defining global variables") even
though the original target driver tolerated it. Reordered inherit to
precede the global declarations in every file (content unchanged
otherwise).
Duplicate inherit ROOM from two rooms merged into one file (u/xxy/shaolin/matou1.lpc)
The file's own header comments read // Room: /d/shaolin/matou1.c AND
// Room: /u/nangong/matou.c — two genuinely different rooms (侠客岛码头
and 南码头) concatenated into one file, each with its own inherit
ROOM;/create(). Since only one object can ever be "live" at this one
path, and the file's own name matches the FIRST room (matou1), removed
the second, dead block (lines 151–178: the 南码头 definition) rather than
guess how to merge them. No /u/nangong/matou file exists anywhere else
in the archive, so this content was already unreachable dead weight
(the duplicate inherit was a hard compile error, meaning this second
room was never actually loadable even in a hypothetical original-driver
boot of this exact archive) — nothing playable was lost.
void functions returning a value (3 files + 1 wrong-type return)
d/city2/npc/{guanfuzi,qianlaob,gaoyanch,xutianch}.lpc'svoid recognize_apprentice(object ob)allreturn 1;/return notify_fail(...)(an int). Changed all 4 toint recognize_apprentice(...).d/zhongzhou/midao.lpc'svoid greeting(object ob)had areturn 1;mid-body (an early-exit idiom, return value unused by any caller found). Changed toint greeting(object ob).u/temp/liwu.lpc'sint accept_object(...)had one branchreturn "你有礼物了呀";(a string, not int) — genuine type mismatch, not a declared-type issue. Changed towrite("你有礼物了呀"); return 0;matching the message-then-return-int convention every other branch in the same function already uses.
std/weapon/gun.lpc — bad inherit target + reused BLADE helper
inherit GUN; — GUN was never a #defined macro anywhere in this
archive (no sibling weapon-type path entry for it in weapon.h either),
and this is the only file in the whole lib referencing it. create()
calls init_blade(25) (a real function only BLADE
provides) confirming this "手提机枪" (submachine gun — an anachronistic
one-off item) was actually meant to inherit BLADE, reusing its damage
helper, not some fabricated GUN base. Fixed to inherit BLADE;.
#include wrong absolute path, one wizard homedir cluster (8 files, u/xxy/shaolin/bagua*.lpc)
All 8 hardcoded #include "/d/shaolin/bagua.h", but the file actually
lives at /u/xxy/shaolin/bagua.h (the header, and the function
check_dirs() it defines, were both effectively unreachable). Fixed the
absolute path in all 8 files — this single header also defines
check_dirs(), so it cleared that "Undefined function" category too in
the same pass.
§8e — tail() is not a real efun (cmds/app/tail.lpc)
Same pattern as the catalog's own first documented case. Reimplemented
do_tail_lpc() in plain LPC (read_file + explode + slice + write),
defined before main() per §8b (a same-file forward call to a
not-yet-defined function fails "Undefined function" here, unlike some
looser old-driver targets).
Confirmed NOT needed (checked proactively, found clean)
- §4 (master's lazy
load_object(SECURITY_D)insidevalid_read/valid_writerecursing to a stack overflow) —master.lpc'svalid_write/valid_readonly usefind_object(), neverload_object();valid_readunconditionallyreturn 1;(very permissive, no daemon dependency for reads at all). No guard needed. - §7 (
get_root_uid()/get_bb_uid()missing) — both already present inmaster.lpc, returningROOT_UID/BACKBONE_UID. - §8c (
valid_read/valid_writeclobbering caller identity withthis_player()) —securityd.lpc'svalid_writeuses the passed-inuserargument directly throughout, nothis_player()override at all; it doesn't even implementvalid_read(master's own hardreturn 1handles all reads). - §15l (master's
create()destructing/reloadingSIMUL_EFUN_OB) —master.lpc create()is a one-linewrite(), no destruct/reload dance. - §15n (custom
securityd'svalid_readACL blocking the driver's own compile-time reads) — moot; master'svalid_readis a hardreturn 1, never defers tosecuritydat all, so this specific gap can't occur here. - §15o (missing
get_include_path()breaking mid-connection#includes) — checked; no<local.h>-next-to-its-user#includepattern found anywhere in the lib (only genuine shared-directory headers likeinclude/net/*.h, mostly for the excludedftpd/network daemons anyway). - §15ag (
ed_start/ed_cmd/query_ed_mode,__OLD_ED__) — grepped, zero hits anywhere in the lib. - §15ah (missing save/log directories silently swallowing
write_file()/log_file()) —feature/save.lpc'ssave()callsassure_file(file)beforesave_object()(a real efun that creates missing parent directories), so the emptydata/user/,data/login/(no per-letter shard subdirectories at all) never actually breaks anything — confirmed by a live registration +saveactually succeeding. Everylog_file()target directory referenced anywhere in the lib (log/static/,log/wiz/, etc.) already exists in the raw archive. - §15ai (dns_master exclusion surfacing a
shutdown(1)gate elsewhere) — grepped everyDNS_MASTER/dns_masterreference in the lib; all are confined toadm/daemons/network/*(the isolated, excluded intermud subsystem itself), nothing inlogind.lpcor any registration-path file references it. - §15aj (missing mandatory gift/first-room object) —
START_ROOM(/d/zhongzhou/yinghao) exists and loads;enter_world()already guards the (rarely-used) custom-startroompath withcatch(load_object(startroom))falling back toSTART_ROOM. - §15ak (extensionless-file/
.c-backup pairs silently promoting the wrong one) — found 9 such pairs (cmds/std/bei,cmds/std/xiuxing,u/panguan/banned_sites,u/temp/100gold,d/mingjiao/{shanlu2, lhqpaifang,tomen1},d/lingjiu/obj/jiudai,daemon/class/huashan/huashan-jianfa/feilong). 6 pairs are byte-identical (no risk either way); the 3 that differ (xiuxing,lhqpaifang,feilong) all have a newer mtime on the.cside, meaning promoting the.c→.lpccopy (this driver's actual resolution order) picks up the more recent edit, not a stale backup — the opposite direction from thezitengzhanprecedent, but the outcome is still correct. None of the 9 pairs are anywhere near the boot/registration/ look/score path (personal wizard homedir + specific zone content only). Left as-is. - §15al (
crypt(str, 0)random-hash-every-call footgun) —logind.lpc'snew_password()/confirm_password()usecrypt(pass,0)correctly for ordinary password storage (compute once at registration, compare later viacrypt(entered, stored_hash), which reuses the real salt embedded instored_hash) — this is the standard, safe idiom, not the two-independent-crypt(KEY,0)-calls client-challenge shape that actually breaks on this driver. No client-challenge/handshake protocol exists in this lib at all. - §15am (
file_size()==-1treated as truthy) — grepped every barefile_size(...)-as-condition site; none found using it as a naked boolean without an explicit comparison. - §15an (live-clock prompt defeating mudclient.py's idle pacing) — no live-updating clock/status in the prompt; used
--idle 0.6throughout anyway as a safety margin, and the transcripts show clean 1:1 send/ response pairing. - §15ao (
switchwith onlydefault:, no realcase) — grepped the whole lib for the shape, zero hits;master.lpc connect()doesn't useswitchat all. - §15ap (
__FILE__inside an#included, notinherited, fragment) — no such usage found. - §15aq (forward reference to a locally-overridden inherited function binding to the wrong body) — not encountered; the one forward-reference fix needed (
cmds/app/tail.lpc'sdo_tail_lpc) was the simpler §8b case (nothing else of that name existed to accidentally bind to). - §8f (
TYPE * a, b;losing the array modifier across a comma list) — grepped for the shape; the only near-matches (feature/condition.lpc'smixed *cnd, err;,adm/daemons/network/telnetd.lpc'sstring *tmp, file;) useerr/fileas genuinely scalar values in their bodies (not arrays), so this isn't the Dead-Souls-style bug — left as-is (andtelnetd.lpcisn't even preloaded). - Uppercase
.Cfiles — found and fixed 7 (d/yangzhou/npc/*.C), renamed to.lpc; confirmed no literal.C"-cased path references anywhere (the 4 room files that spawn these NPCs reference them via__DIR__"npc/name", extensionless). static→nosavefalse positives —convert_lib.sh's blanket sed hit 10 genuinelog_file("static/...", ...)string-literal path references (the on-disklog/static/directory convention, same counterexample shape asmoniHuafu/archive #57), turning them into"nosave/...". Reverted all 10 back to"static/"across 8 files after the mechanical conversion pass, before any other edit.- §13-style content gaps, documented not fabricated:
- F_UNIQUE (51 files inherit it) — no /feature/unique.lpc exists
anywhere in this archive at all (present in nearly every sibling ES
II lib in this project, genuinely absent here). Left undefined/
unfixed; these files won't compile, none are on any preload path.
- STICK/MACE/RAKE/BOW/ARCHERY (weapon-type path macros, 17+11+4+1+1
files) and F_FIGHTER/F_CLOTH/DAEMON (2+2+4 files) — none defined
anywhere in include/, and (unlike the armor.h/F_SSERVER cases above)
not simply commented out either — genuinely absent content, not a
mechanical omission to restore.
- prepare_skill() (33 files), get_npc_data()/set_npc_data() (12
files) — called everywhere, defined nowhere in the whole archive (not
even a stub). No sibling ES II lib in this project defines these
either (checked), so nothing to port from. NPC-combat-setup and
NPC-stat-persistence features this specific archive never shipped a
working implementation for.
- daemon/skill/old/jiuyin-shengong.lpc's ::hit_ob(...) (1 file) —
FORCE (std/force.lpc) never defines a base hit_ob, so the ::
parent-call has nothing to reach. Isolated, single file.
- u/xxy/city2/npc/shenzhao.lpc's #include "/kungfu/class/shaolin/hui.h"
(2 files) and u/aug_old/{yapu1,thd/zhou_botong}.lpc's
#include "thd.h"/"npc.h" — target files genuinely don't exist
anywhere in the archive (unlike the bagua.h case, this isn't a
wrong-path typo with the real file sitting elsewhere).
- A long tail of smaller isolated one-off/few-file categories in the
remaining lpcc_fail.log entries (mud_name, set_encumbrance,
member_group — mostly unreachable adm/daemons/network/* files,
set_max_items, data_netmail_file, a handful of "Bad assignment
(mapping vs unknown)"/"syntax error" entries scattered across
personal wizard homedirs u/aug_old, u/xxy, u/panguan, u/temp)
— each affects 1-2 files, none on the boot/registration/gameplay
path exercised by this pass's testing. Not investigated further per
the project's stated "breadth over exhaustive depth" priority.
WASM-enablement pass (loopback-allow / admin seeding)
Applied the four standard WASM-first changes (AGENTS.md §1.3b/§1.3e/§1.5):
1. Loopback always allowed — ban gate (adm/daemons/logind.lpc:48-64)
logon() unconditionally ran BAN_D->is_banned(query_ip_name(ob)) /
BAN_D->is_banned(query_ip_number(ob)) and destructed on a hit. Wrapped
the ban block so it only runs for a non-loopback remote address.
Retrofitted fail-open → fail-closed (2026-07-24): the gate as
originally patched here ran the ban check only when
stringp(ip) && ip != "127.0.0.1" && strsrch(ip, "127.") != 0 &&
sscanf(ip, "%*d.%*d.%*d.%*d") == 4 — i.e. it required the ip to
successfully parse as a well-formed dotted-quad before the ban check
would even run, so ANY malformed/unparseable ip silently skipped the
ban gate entirely (fail-open), not just genuine loopback. This was
written defensively against the old WASM driver bug where
query_ip_number() returned garbage for every WASM connection; that
driver bug is now fixed (WASM reports a clean "127.0.0.1" same as
native), so there is no remaining justification for treating "can't
parse it" as "must be loopback". Changed to fail-closed: if
(!(stringp(ip) && (ip == "127.0.0.1" || strsrch(ip, "127.") == 0)))
— only a real loopback-shaped string skips the ban check; anything
else, including an unparseable/non-string ip, now goes through the
normal ban logic same as any other remote connection.
2. Uptime startup gates — none present
No uptime() < N connection-rejection gate exists in this lib. The
uptime() hits are all in-game gambling rooms (d/*/duchang*.lpc,
npc/douji, npc/saigui) and the cosmetic cmds/usr/uptime.lpc /
adm/daemons/network/cmwhod.lpc uptime display — game content, left alone.
3. Anti-flood throttles — none present
No per-IP connection-rate / multi-login-per-IP / registration throttle in
logind.lpc (only a MAX_USERS cap and a wiz_lock_level gate, neither
IP-based). Nothing to exempt.
4. Admin account seeded — fluffos / Mud@2026 / 浮浮
Registered through the real flow (id fluffos → y → 浮浮 → Mud@2026
×2 → email → m), landed in 英豪酒楼. Granted (admin) by appending
fluffos (admin) to adm/etc/wizlist (the file securityd.lpc:82
reads into wiz_status; get_status/wizhood return (admin), which
feature/command.lpc:90 maps to ADM_PATH + enable_wizard()).
Verified after reboot: login as fluffos, update /adm/daemons/logind
→ 重新编译 ... 成功, who4 wizard listing works.
Save files for the orchestrator to force-add (currently untracked, NOT gitignored — a plain add works, listed for completeness):
libs/tiexuejianghu/work/data/user/f/fluffos.olibs/tiexuejianghu/work/data/login/f/fluffos.o
Retest: fresh normal registration (秦十/qinshi) still reaches 英豪酒楼; debug.log had 0 runtime errors across the session; test char qinshi removed afterward (fluffos kept).
Re-retest after the fail-closed retrofit (2026-07-24): fresh boot,
fresh normal registration (id qinretes, real Chinese name 秦风七) all
the way through look/score/quit — landed in 英豪酒楼, correct
output throughout, normal 30-second delayed-quit message. fluffos/
Mud@2026 admin login verified again: look then update
/adm/daemons/logind → 重新编译 /adm/daemons/logind.lpc:成功!. Zero
执行时段错误 lines in debug.log for the whole session. Test char
qinretes removed afterward (fluffos kept).
Registration-flow + post-login-command transcripts
Three full end-to-end runs, each in ONE continuous mudclient.py
connection (--idle 0.6), across three different driver boots (to also
re-verify the emoted.o fix and the full set of source fixes together):
Run 1 (after emoted.o fix, before the lpcc-sweep-driven content fixes):
qinfg → y → 秦风二 → test123 (×2) → [email protected] → m →
look → score → quit. Landed in 英豪酒楼; look printed the real
room description twice (before/after an NPC "耳光" interaction event);
score printed 普通百姓 秦风二(Qinfg), correct stats/HP bars/food/water
gauges; quit gave the normal 档案正在存取中,三十秒后方能下线! delayed-
quit message. Zero 执行时段错误 (runtime error) lines in debug.log for
this session.
Run 2 (after ALL fixes above, fresh boot): tiexue → y → 秦风三 →
test123 (×2) → [email protected] → m → look → score → quit.
Landed in 英豪酒楼; look ×2 correct; score printed 普通百姓
秦风三(Tiexue), correct stats; NPC "武大郎" random_chat fired (previously
the emoted-restore bug made this crash with Bad argument 1 to keys()
every ~heartbeat — now silent/clean); quit gave the normal delayed-quit
message. Zero runtime errors in debug.log.
Run 3 (final re-verification after the very last two fixes —
gun.lpc/tail.lpc — neither on the registration path, run anyway for
completeness): muyuan → y → 秦风四 → test123 (×2) →
[email protected] → f (female, to also exercise the alternate
gender/clothing branch in enter_world()) → look → score → quit.
Landed in 英豪酒楼; look ×2 correct; score printed 普通百姓
秦风四(Muyuan), 女性 (female), correct stats/gauges; quit gave the
normal delayed-quit message. Zero 执行时段错误 lines in debug.log
for the entire session (grep -c confirmed 0).
All three runs used a real Chinese given name (2–3 characters), confirming
the §15h is_chinese/check_legal_name fix works correctly end-to-end,
not just in isolation.
lpcc_check.sh sweep results
Ran the full sweep three times as fixes progressed (9190-9191 .lpc
files, not a mega-lib, full sweep is the required gate per AGENTS.md):
- Before any lpcc-driven fixes: 8332/9191 pass (90.65%).
- After the armor.h/F_SSERVER/skill.lpc/bagua-path/inherit-order/ matou1/gengfu/hmeng014/recognize_apprentice/greeting/accept_object fixes: 8449/9190 pass (91.96%) — file count dropped by 1 from the
d/sandboy/map.lpc→.txtrename. - Final (after
gun.lpc/tail.lpc): a few more files pass but a full re-sweep wasn't re-run after these last two single-file fixes (each individually confirmed clean via directlpccon that exact path) — the 91.96% figure is the last full-sweep baseline; true final pass count is at least 8451/9190.
Remaining ~740 failures are dominated by the documented content gaps
above (F_UNIQUE alone accounts for ~51 files, prepare_skill/
get_npc_data/set_npc_data another ~56, the weapon-type/feature macros
another ~35), the known #include-fragment sweep-artifact category
(_axe.lpc/_blade.lpc/_sword.lpc/_dagger.lpc-style #define
AS_FEATURE; #include "X.lpc" files failing standalone with Unable to
find the inherited function 'setup' — confirmed via grep that this
exact error string never appears in the real boot's debug.log, matching
§6b's documented false-positive pattern exactly), and a long tail of
1-2-file isolated content issues in personal wizard homedirs, none on the
registration/gameplay path this pass tested.
Re-verification pass (driver rebuild + LPC formatter + WASM build)
- Reformatted all 9190
.lpcfiles underwork/withtools/lpc-syntax/format-corpus.mjs(Node): 9102 written, 58 already idempotent-clean, 30 refused (self-checked token/byte-identity guard, expected on messy legacy code, not chased). Verified afterward that the §15ae fix (feature/command.lpc'scommand_hookstayingnomaskwithprivatestill commented out) and the §15t inherit-ordering/absolute- include-path fixes from the original pass all survived the reformat unchanged (spot-checked directly, plus the boot/registration retest below exercises them at runtime). - Native retest against the freshly-rebuilt driver (
~/src/fluffos/build-debug/src/driver, rebuilt from latest upstream master): clean boot, zero fatal errors indebug.log. Full registration flow re-verified with a fresh real Chinese name (秦风六/idqtretest) throughlook/score/quit, landing in英豪酒楼exactly as before — no regressions from either the driver rebuild or the reformat. - WASM build test (
scripts/wasm_client.jsagainst~/src/fluffos/build-wasm/src): boots cleanly (only the expected benign compile-warning spam and non-fatal preload notices, same as native). Full registration completed end-to-end under WASM too — idwasmtxq→ real Chinese name秦枫→ password/email/gender → landed in英豪酒楼,look/score/quitall produced correct output. This lib has no IP-format-dependent login gate, so it isn't affected by the knownquery_ip_number()WASM limitation — fully playable under WASM.
深度功能测试 / Deep functional test (2026-07-24)
Round-two deep playthrough pass (AGENTS.md §10.7), following the
bxsj/xiyouji worked examples. Played as an ordinary new player
through registration, exploration, organic skill-learning, sect-joining,
safe and lethal combat, a real quit, a real-wall-clock-gap reconnect,
and (unusually for this project's round-two passes so far) a full
death/reincarnation cycle, native driver (build-debug). Read
doc/help/newbie in full first — it named the intended test path
(中州城's 英豪酒楼 start, hp/cha/score/look, the menpai/帮会
sect list, xue <skill> from <teacher> syntax) but, notably, said
nothing about a safe-sparring mechanism — that had to be found by
grepping accept_fight/room source, and turned out to be gated behind
an in-game cost a fresh character can't pay (see below).
Test characters (both kept, not cleaned up, as representative playthrough evidence):
- id
qinlangf, Chinese name 秦朗风, passwordTest1234, male — the main playthrough character. State: apprenticed to 谷虚道长 (Wudang/武当派, 4th-generation disciple,武当派第四代弟子), learnedliterate(读书写字) to level 1 via the organic teacher-NPC path, survived a fullquit+ real-wall-clock-gap reconnect with sect membership and skill intact. Saves:work/data/user/q/qinlangf.o,work/data/login/q/qinlangf.o. - id
linzhu, Chinese name 林铸, passwordTest1234, male — a second, disposable character used for combat testing (safefight, then a deliberately lethalkill, real death, and a full reincarnation round-trip). Saves:work/data/user/l/linzhu.o,work/data/login/l/linzhu.o.
Bug found and fixed #1: already-cataloged §7.12 class, live-reproduced here for the first time
adm/simul_efun/message.lpc:61-62's tell_room(mixed ob, string str,
object *exclude) wrapper passes the (omitted-when-not-given) exclude
varargs parameter straight through to the message() efun, which on
this driver resolves an unsupplied array-typed varargs argument to raw
int 0, not ({}). message() requires its exclude argument to be an
object or array — this is exactly AGENTS.md §7.12 ("Shared
message/wrapper argument bugs"), already documented as affecting "most
of the ES II family," which tiexuejianghu is (per this file's own
lineage section) — but this lib's original conversion pass never
checked for it, and it shipped live.
- Symptom, live-reproduced twice in this session: any 2-argument call to
tell_room(room, msg)(158 of 348 call sites in this lib use the 2-arg form) crashes withBad argument 4 to EFUN message() Expected: object, array, Got: int(0)the moment it actually runs. Confirmed live via/obj/user.lpc:69'suser_dump(DUMP_NET_DEAD)— the routine that announces "so-and-so 断线超过 N 分钟,自动退出这个 世界" once a dropped connection'sNET_DEAD_TIMEOUT(300s) elapses — which crashed for both test characters (林铸and秦朗风) independently after their sessions net-dead'd, i.e. this fires for any player whose connection drops without a cleanquit(browser close, network blip, client crash) — about as common an event as exists in an online mud. The crash is caught by the driver (the disconnect itself still completes), so it's invisible on-screen by construction — exactly the class of bug this methodology exists to catch. - Fix (the exact documented §7.12 fix):
exclude || ({}).
``lpc
// before
varargs void tell_room(mixed ob, string str, object *exclude) {
if (ob) message("tell_room", str, ob, exclude);
}
// after
varargs void tell_room(mixed ob, string str, object *exclude) {
if (ob) message("tell_room", str, ob, exclude || ({}));
}
``
- Verified: reproduced live pre-fix (
debug.logcaptured the exact trace twice, once per test character, blaminguser.lpc'suser_dump()→simul_efun.lpc'stell_room()). Fix applied,update /adm/simul_efun/messagerecompiled clean as admin (fluffos/Mud@2026). Not re-verified against a live repeat of the same 300-second net-dead timeout given the time budget — a genuine wait that long wasn't repeated post-fix. Confidence is still high: this is a one-line change identical to the already-proven fix deployed on multiple sibling ES II libs in this corpus, the file compiles clean, and the bug's mechanism (an omitted varargs array resolving toint 0on this driver) is independent of which caller triggers it — any other 2-argtell_room()call site exercised during the rest of this session (there are 158) would have hit the identical crash and did not, because none of the other 157 happened to run during this particular playthrough, not because this one is special.
Bug found and fixed #2: NEW bug class — a hardcoded respawn-room path stale from an old, since-replaced zone rewrite
include/login.h:14's REVIVE_ROOM constant ("/d/yangzhou/temple")
does not point at a loadable object. d/death/npc/{wgargoyle,
bgargoyle}.lpc (白无常/黑无常, the two death-realm psychopomp NPCs) both
run a 5-stage, 5-second-interval dialogue (death_stage()) after a
player dies, then call ob->reincarnate(); ob->move(REVIVE_ROOM); to
send the player back to the living world.
- Symptom, live-reproduced twice:
kill liumang(a genuinely lethal fight, as opposed to the non-lethalfightcommand — see combat section below) killed林铸; the death sequence correctly created a corpse, moved the player toDEATH_ROOM(/d/death/gate, 鬼门关), and ran all 5 stages of 白无常's dialogue over ~25 real seconds — then crashed:*call_other() couldn't find object '/d/yangzhou/temple'., raised fromfeature/move.lpc:54'smove(), called fromwgargoyle.lpc:56'sdeath_stage(). The crash is caught (the driver's error handler swallows it, same as every other bug in this catalog), so the player-visible effect is silent: the dialogue simply stops advancing and the player is left standing in 鬼门关 forever, never actually returned to the living world, with no error message and no indication anything went wrong — indistinguishable from the game just being slow, unlessdebug.logis checked. Every player death in this game runs through this exact code path, making this among the highest-blast-radius bugs found in this project's round-two pass so far (every death, not just some). - Root cause:
d/yangzhou/temple.lpcdoesn't exist in the lived/yangzhou/zone — but it DOES exist, verbatim, underd/yz_bak/yangzhou/temple.lpc. Comparing the two directories' file listings showsd/yangzhou/andd/yz_bak/yangzhou/are two entirely different, incompatible room sets that happen to share a directory name (77 files each, near-zero filename overlap) — not a newer/older revision of the same zone, but two unrelated wizard-authored "Yangzhou" builds, one of which (now underyz_bak/) was fully superseded and disconnected from the live map, the other becoming the currentd/yangzhou/.REVIVE_ROOM's path was written for the old, now-archived zone and never updated when the zone was replaced — a genuinely new bug class for this project's catalog: a hardcoded room-path constant left stale after a zone got wholesale replaced during the original game's own development, as opposed to every previously-cataloged path bug in this project (which are all conversion-era typos/renames). This is NOT the same shape as AGENTS.md's existing "content gap, documented not fabricated" pattern either — the target content still exists, just under a disconnected, deliberately-superseded backup directory, so resurrecting it by pointing back at the old path would reconnect stale, replaced content into the live map rather than fix the actual bug. - Fix: repointed
REVIVE_ROOMatSTART_ROOM(/d/zhongzhou/ yinghao, always-loadable, and already the exact fallbackenter_world()itself uses for a broken/missing custom startroom — see the "Confirmed NOT needed" §15aj entry above) rather than at the disconnected old zone:
``lpc
// before
#define REVIVE_ROOM "/d/yangzhou/temple"
// after (see the file for the full comment explaining why)
#define REVIVE_ROOM START_ROOM
``
- Verified: reproduced live pre-fix twice (once accidentally mid-testing before the fix was written, once deliberately, both times identical crash + identical debug.log trace). Post-fix: killed
林铸a second time viakill liumangfrom a freshly restarted driver (clean boot, zero errors), let the full 5-stage/~25-second 白无常 dialogue play out for real (--idle 4, several blank sends — the earlier pre-fix attempts under-waited and only proved the crash was still reachable, not yet that the fix worked), and confirmed the character landed cleanly in英豪酒楼afterward with zero new debug.log lines for the entire death→dialogue→reincarnation sequence.bgargoyle.lpc(the parallel 黑无常/"evil path" version of the same flow, presumably for players who die dishonorably) shares the identicalREVIVE_ROOMcall and is fixed by the samelogin.hchange, but was not itself live-reproduced — flagged as fixed by code-shape match, not independently verified.
Minor logic bug found and fixed (not crash-class, but confirmed via live incorrect behavior): 徐霞客's answer-window timer had its subtraction backwards
d/zhongzhou/npc/xuxiake.lpc:99's do_answer() — part of this NPC's
"answer my trivia question before I'll teach you 读书写字" apprenticeship
gate (the organic-skill-learning path this session used) — computed
now_time = (int)ob->query_temp("徐/time") - time(); (stored-question-
time minus now), which is always negative or zero and can never exceed
the intended 10-second answer window (if (now_time > 10)), rather than
time() - stored_time (elapsed, positive, correctly comparable to the
window). Discovered live: an unanswered question never expired even
across brute-force wrong guesses tried well outside any reasonable
10-second window, and (worse for a tester relying on the intended
"say the question again if you got it wrong" UX) the question is only
generated once per xue attempt (guarded by if
(ob->query_temp("徐/answer")) return notify_fail(...) at the top of
recognize_apprentice()), so a player who doesn't see the question text
in time (this project's own mudclient.py --idle pacing raced the
question's own 1-second call_out delay on the first attempt) is stuck
re-guessing the SAME never-re-rolled question indefinitely rather than
getting a fresh one after 10 seconds as designed. Not a crash — the
broken timer makes the puzzle strictly easier (never expires) rather
than broken/unplayable, so it's a genuine but low-severity bug. Fixed
the subtraction order:
// before
now_time = (int)ob->query_temp("徐/time") - time();
// after
now_time = time() - (int)ob->query_temp("徐/time");Verified: update /d/zhongzhou/npc/xuxiake recompiled clean as admin;
re-tested the full organic-learning flow end-to-end post-fix (xue
literate from xu xiake → question → answer 22 → learned) — unaffected
for the correct-answer-in-time case, which is all that was re-verified
live; the now-correctly-enforced 10-second expiry itself wasn't
separately re-timed live (low value given the trivial, mechanical
nature of the fix).
What was tested and confirmed working
- Registration: real Chinese name (秦朗风), full flow (id → confirm new character → Chinese name → password ×2 → email → gender), landing in
英豪酒楼(South-City-Inn-equivalent,d/zhongzhou/yinghao.lpc). A second independent registration (林铸/linzhu) confirmed the same flow twice. - Movement/exploration: walked from
英豪酒楼through文定北街→市中心→延陵东路(流氓/丫鬟 wild NPCs, a small自助餐厅restaurant/shop) → south to书院(d/zhongzhou/shuyuan.lpc, 徐霞客's academy) and separately the long overland route to 武当山 (南城门 →叉路口→ a randomized "can't tell which way" maze room,草丛, which took several retries of the same direction to escape by design — not a bug, an intentional random-navigation obstacle — → up the mountain through太子坡/小吃店/紫霄宫/十八盘/武当广场to三清殿). Room descriptions, exits, and NPC presence all rendered correctly throughout on a first-ever visit to every room walked, including三清殿itself (see "first-visit reentrancy check" below). - First-visit §7.17-class reentrancy check:
三清殿(which populates 2 NPCs, 谷虚道长 and 宋远桥, viastd/room.lpc'ssetup()→reset()→make_inventory()chain — the exact same structural shape documented in AGENTS.md §7.17 asxiyouji's root cause #1) was this character's first-ever visit to that room on a freshly booted driver. No crash, no duplicate NPCs, no corrupted"0"in either NPC's title —debug.logonly gained benign compile warnings (Illegal to declare nosave function, an unrelated pre-existingdbase.hwarning seen throughout this lib) from that visit. This lib does NOT have this lineage'screate_identity()/ forced-call_other-self-locate idiom anywhere (grepped, zero hits), which per §7.17's own analysis is the second, lib-specific half needed to close the reentrancy cycle into an actual crash — sostd/room.lpc's shared double-reset()shape alone is (as §7.17 itself found forxiyouji) not sufficient by itself to reproduce the crash here. Not treated as a bug requiring a fix; recorded because checking it was part of the methodology. - Character info:
score,hp,i, andcha(own skill list) all correct at every stage (fresh, post-skill-learn, post-sect-join, post-death/reincarnation, post-relogin). - Skills — organic teacher-NPC path:
d/zhongzhou/shuyuan.lpc's 徐霞客 (xuxiake.lpc) gatesrecognize_apprentice()behind a trivia-question/answermini-game (see bug above) rather than an unconditional grant like some sibling libs'jiaotou-style NPCs —xue literate from xu xiake→ question →answer 22(his age when he left home) → "你听了徐霞客的指导,似乎有些心得。你的「读书写字」进步 了!" →chacorrectly showed读书写字 (literate) - 新学乍用 1/0. Confirmsxue/learn(identical files) work end-to-end. - Sect-joining — organic path:
help newbiedocuments 14 门派 (sects, direct-apprentice viabai) and 4 NPC-led 帮会 (guilds); no newbie-gift shortcut exists in this lib (grepped, none found — unlikebxsj'sshizhe.lpc). Walked to 武当山's三清殿, found 谷虚道长 (d/wudang/npc/guxu.lpc), whoseattempt_apprentice()gate ismingwang < 0— trivially satisfied by a fresh character'smingwang == 0— vs. 宋远桥/z.lpc/zhang.lpc/yu.lpcin the same room/zone, which requiremingwangfrom 2,000 up to 100,000 (a fresh character has 0).bai guxu→ "谷虚道长决定收你为弟子。...恭喜您成为 武当派的第四代弟子。" —scoreafterward correctly showed武当派第四代弟子 秦朗风and "你的师父是谷虚道长". This lib gates its various sect-master NPCs at genuinely different newbie-accessibility tiers by design (matchinghelp newbie's "在门派中可以直接拜师傅学 艺" claim for at least the most junior teacher per sect) — not a bug, but worth noting for future testers: don't assume the FIRST sect-master NPC found accepts newbies; checkattempt_apprentice()'s gate or just trybaion more than one. - Combat — safe path attempted, found genuinely gated, substituted: this lib's own designated "safe" combat venue is
d/zhongzhou/ biwuchang.lpc's referee-supervised PvP arena (biwu <player>invite/accept handshake, auto-halts akee≤50%-max loser viad/zhongzhou/npc/caipan.lpc'sdo_bihua()) — but its entrance courtyard (biwuchangyuan.lpc) is gated behind a门卫(guard) NPC requiring a ≥20000-money bribe (accept_object()ind/zhongzhou/npc/guard.lpc:53) beforevalid_leave()allowsupinto the arena proper. A genuinely fresh character has 0 starting money (confirmed:enter_world()/logind.lpcgrants no starting cash; alistat the nearby 自助餐厅 shop confirmed real, cheap prices — 10-20 文铜板 — that are still unaffordable at 0 money). This specific mechanism was NOT reached live — an honest, explicitly-flagged gap, not a silent skip, per the task's own instructions: a genuinely fresh newbie cannot reach this lib's designated safe-sparring venue without first earning money through some other, unexplored system (quests, selling loot, etc.), which was outside this session's time budget. Substituted with the general "fight vs kill" safety mechanism this lib documents inhelp combat/cmds/std/fight.lpc's own help text instead:fight <npc>is explicitly non-lethal ("只会消耗体力,不会真的受伤") vskill <npc>which is genuinely lethal. Testedfight liumang(a weak,attitude: peacefulstreet-NPC,d/zhongzhou/npc/liumang.lpc) — full turn-by-turn combat log, correctly auto-conceded ("这场比试算我输 了,佩服,佩服!") once resources dropped low, no injury,实战经验(combat exp) correctly incremented 0→3.wimpy <N>(the general flee-threshold command) was also set and confirmed to have no effect onfight's own separate, hardcoded auto-concede threshold (testedwimpy 0, the auto-concede still fired) — these are two independent safety mechanisms, not a bug (std/char.lpc:94-101'swimpy-driven auto-flee only applies to a liveis_fighting()heart- beat check withwimpy_ratio > 0;fight's own concede narration inadm/daemons/combatd.lpc'swinner_msgarray is a separate, independent, always-on mechanism for the non-lethal command). - Combat — lethal path and death/reincarnation, reached live:
kill liumang(same weak NPC, but via the genuinely lethal command) produced real injury narration and, after several exchanges,你死了。— a real player death. Confirmed the death→corpse→DEATH_ROOM(鬼门关)→白无常-dialogue→reincarnation→START_ROOMround-trip end-to-end post-fix (see Bug #2 above);scorein the interim death-realm state correctly showed the孤魂野鬼(lost-soul) title and aghost-flagged reduced stat display. This satisfies the checklist's "get as far as reasonably possible toward combat/death" item in full — death was not just attempted but completed, in both the broken (pre-fix) and working (post-fix) forms. - Shop purchase — NOT completed live, explicit reason: reached a real shop (
李老板's 自助餐厅,listcorrectly showed real items — 辣椒/盐巴/酱油/香油 at 10-20 文铜板 each) but could notbuyanything: a genuinely fresh character has 0 starting money in this lib (confirmed by inventory inspection — only default clothing, no currency object, and no starting-cash grant found anywhere inlogind.lpc/enter_world()). This is the same root gate that blocksbiwuchangabove. Earning starting capital (quests, selling loot, begging, etc.) was not pursued given the time budget already spent on navigation and the two crash-class bugs found — flagged here explicitly rather than silently presented as tested. - Persistence: confirmed across a real
quit+ a genuine ~80-second wall-clock gap (backgroundsleep 80, not merely a fast reconnect) + fresh full re-login forqinlangf: sect membership (武当派第四代弟子, "你的师父是谷虚道长") and skill (读书写字 1/0) both round-tripped correctly. Room position does not persist across a realquit(enter_world()always lands a full login atSTART_ROOMregardless of where the character quit) — confirmed intentional design matching this session's own earlier admin-seeding notes, not a bug. Inventory:quitcorrectly dropped the (non- autoload, non-unique) starting clothes ("你丢下一双皮靴。...因为这 样东西并不值钱,所以人们并不会注意到它的存在。") and a fresh full login re-granted a (randomly re-rolled, this time 蓝马褂 instead of the original 紫蟒袍) default outfit — the same deliberate ES-II-family anti-hoarding-on-quit design already documented inbxsj's deep-test section, not a bug specific to this lib. Also separately confirmed the silent-reconnect path (a fresh connection within the same session, before any realquit, viaid+password) re-attaches the same live body with zero state loss — used throughout this session betweenmudclient.pyinvocations. - Debug.log hygiene: grepped after every
quitin this session, not just after login, per the methodology's central lesson — clean every time except for the two live-reproduced bugs above (both now fixed and re-verified clean).
Process/testing note for future agents on this lib
Room navigation via a static regex-based BFS over set("exits", ([...
])) literals (as used successfully on other libs in this project) is
not fully reliable here for two lib-specific reasons hit live during
this pass: (1) some rooms (e.g. d/yeyangzai/caocong, "草丛") implement
a randomized "you can't tell which direction" maze where the SAME
direction command must be retried a variable number of times before it
actually succeeds — a static shortest-path graph can't capture this;
(2) mudclient.py sessions are not persistent connections across
separate invocations in this project's usual workflow, so a character's
*actual* position when a new session logs in is wherever the PREVIOUS
session left it (via silent reconnect), not the game's own START_ROOM
— sending a route computed from START_ROOM after actually reconnecting
mid-route produces a string of 什么? ("what?") rejections that are
easy to misdiagnose as a game bug rather than a test-script coordinate
error. Verify current position with look before sending a long
movement queue, especially after any prior session that didn't end in a
full room-resetting quit.
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 47 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
深度功能测试(2026-08-13,round two,新驱动重测)
Re-tested against the freshly-rebuilt build-debug/src/driver(post
全库 quest_times/win_times %-operator 修复 + Warning/warning
驱动文本回退)。log_error()(adm/obj/master.lpc,CRLF 行尾档
案)已经在更早一轮(引用注释里的"AGENTS.md #15w")正确修复过,管
理员账号(fluffos/Mud@2026,adm/etc/wizlist 已有
fluffos (admin) 且存档已提交)也已经全部正确,本轮只发现并修复
了 log_file() 一处。
发现并修复的 PROGRAMMING bug
1. log_file()(adm/simul_efun/file.lpc,CRLF 行尾档案)完全没
有 assure_file() 保护(AGENTS.md §7.11-class 的又一确认实
例):cmds/app/{clone,rm,update}.lpc/cmds/wiz(/arch)/
summon.lpc 等文件多处 log_file("wiz/<子目录>/<id>.log", ...)
调用依赖对应子目录存在,其中 wiz/update/<id>.log 每次巫师执
行 update 指令都会触发,本轮的 update 验证步骤本身就顺带验
证了这个修复。注册/登录本身只写 log_file("USAGE", ...)(无子
目录,本来就存在),不受影响。已补上
assure_file(LOG_DIR + file);(含前向声明,用 Python 字节级替
换保留原 CRLF 行尾格式)。
Proactive checks(无需改动)
win_times修复确认存在且正确:d/city2/npc/refereew.lpc:177; 姊妹文件u/xxy/city2/npc/refereew.lpc:176同样已修。- 未发现
message()simul_efun 包装函数——不适用 message()-missing-varargs 这一类 bug。 logon()没有 GB/Big5 选码提示,也没有"Press Enter to Continue"分页步骤——直接进英文 id 提示,本轮读代码确认后未误踩。
实测过程
用已提交的 fluffos/Mud@2026 登录,update /adm/simul_efun/file
(就是本轮改过的文件)确认可正常重新编译,零诊断刷屏。全程未生成
log/debug.log(说明真的零运行期错误,不是文件被清空)。登录本
身产生的存档时间戳类微小 diff 已用 git checkout 撤销,不提交。
驱动最终按精确 PID kill,ps -p 确认已退出。
AGENTS.md §7.100 修复(2026-08-19,批次五)
ROOM 基类冗余 replace_program(ROOM); 自崩溃地雷(详见 AGENTS.md
§7.100):3010 个房间文件的 create() 里紧跟 inherit ROOM; 之后
都有这一行多余调用,永久设下"待替换"标记,第一次对该房间对象绑
定闭包就会崩溃。有 5 处代码生成模板烤了同一个地雷(obj/roommaker.lpc、
d/obj/clone/misc/roommaker.lpc、obj/rmmaker.lpc、
u/panguan/rmmaker.lpc、u/panguan/room.lpc——和手足档案 fys 同一
套模板家族)。
本档案独有的新变体(fys 没有):u/heart/xuedao/ 下 143 个文件的
冗余调用和一行 UTF-8 尾随注释共享同一行
(replace_program(ROOM); //如果没有init函数请不要删除这句话),
严格的独立成行脚本正确地跳过了它——另写了一个针对这个精确行形状
的脚本手动摘除。累计 3012 处 live 调用删除,和 survey 记录的数字精
确吻合,修复后 0 处遗留。
验证:build-debug 驱动真实冷启动,端口 40087 正常监听,
debug.log 全程干净。既有管理员账号 fluffos/Mud@2026 登录正常
(落地英豪酒楼,look/quit),全程无新增
"cannot replace"/"cannot bind" 日志行。
§7.30 uninitialized-mapping accessor sweep (2026-08-20)
Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage
bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2
via round-four testing): 3 accessor(s) in this file returned a raw
never-initialized mapping instance variable (defaults to int 0,
not ([]), until first assigned), crashing any unguarded
keys()/sizeof()/indexing caller for a fresh/untrained character.
Fixed at the accessor level (mapp(x) ? x : ([])) per the documented
remedy. Verified via lpcc --batch static compile check only (not a
live boot) as part of a large mechanical sweep; not individually
functionally re-tested live on this lib.
AGENTS.md §7.19: enable_player() reentrancy guard (2026-09-01)
Same corpus-wide bug class as mhxy/wuhanzhan: feature/command.lpc's
enable_player() wraps enable_commands() and is unconditionally
reachable from an NPC's init() via setup()/reset_me() (confirmed
on this lib's own d/*/npc/zhangmen*.lpc-family NPCs, matching
mhxy's originally-documented d/xueshan/npc/zhangmen.lpc pattern).
Calling enable_commands() on an object that's already living()
makes the driver re-invoke that object's init() as a side effect;
since init() calls back into enable_player(), that is genuine
same-call-stack reentrancy that repeats until "Too deep recursion"
aborts a room's first-ever visit.
Fixed with a true reentrancy flag (nosave private int
in_enable_player_now;), NOT a bare if (living(this_object()))
return; guard — this lib's feature/damage.lpc revive() and
cmds/std/sleep.lpc wakeup()/wakeup2() all legitimately
re-invoke enable_player() while the object is still living()
(that's how a fainted/asleep character gets commands back), so a
living()-gated guard would silently break every one of those real
re-enables. enable_player()'s single body has no early return
statements, so the flag is set at entry and cleared once, before the
function's fall-through end. Verified with a single-file lpcc
compile check (exit 0, no errors) against feature/command.lpc.
深度功能测试(2026-09-04,shop)
Live pass, port 40087. 2026-07-24 already apprenticed qinlangf to
谷虚道长 (武当派); this round is shop only. First send is the English
id (no GB/BIG5 menu). Admin fluffos / Mud@2026 lands at 英豪酒楼
(/d/zhongzhou/yinghao) with 武大郎 present.
Shop: list on 武大郎 (d/zhongzhou/npc/wudalang.lpc, F_VENDOR)
shows 烤鸡腿 三十文铜板 (key jitui). clone /obj/money/gold then
buy jitui from wu dalang succeeded: “你向武大郎买下一根烤鸡腿”,
inventory 烤鸡腿 + 九十九两银子 + 七十文钱. can_afford()'s 零钱
checks are already commented out here (Huang 1996 auto-convert), so
gold-only is fine. 武大郎 random_chat emotes — idle 0.45.
No code change. 拜师 not re-done.
深度功能测试(§10.7,2026-10-04)— negative range ends
scripts/lpc_fix_negative_ranges.py: 17 line(s) in 5 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)— undefined macro and simul_efun gaps
message_combatd(msg, me, you)is called by 3 file(s) (the perform files) and defined nowhere in this archive (a simul_efun of the original server): 1 of them did not compile (Undefined function message_combatd).adm/simul_efun/message.lpcnow hasvarargs void message_combatd(string msg, object me, object you, mixed extra)callingmessage_vision(), placed aftermessage_vision's definition (KB 04 §6.2). All callers compile.
深度功能测试(§10.7,2026-10-05)— here-document terminators
scripts/lpc_fix_heredoc_terminator.py --all --apply: 4 here-document block(s) repaired (4 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: d/wudang/bolin.lpc, u/xxy/room/heimuya/shenggu.lpc, u/xxy/room/heimuya/tang.lpc, u/xxy/room/heimuya/npc/tang.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-05)— 房间列出的物件缺档时房间照常加载
房间基类 std/room.lpc:make_inventory() 用 catch() 包住 new(file),做不出来就返回 0;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。
深度功能测试(§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):d/obj/inherit/weapon/throwing.lpc、d/obj/inherit/weapon/fork.lpc、d/obj/inherit/weapon/whip.lpc、d/obj/inherit/weapon/sword.lpc、d/obj/inherit/weapon/axe.lpc、d/obj/inherit/weapon/blade.lpc、等共 9 个。改动的文件在 HEAD 与工作树分别加载(新进程),无回退。
深度功能测试(§10.7,2026-10-07)— 编译警告整理
scripts/lpc_warnings.py tiexuejianghu --fix 加 scripts/lpc_fix_no_effect.py --apply,共改动 535 个 .lpc 和 4 个 .h(多为删去未用的局部变量)。HEAD 与工作树分别加载(新进程):490 -> 490 通过,无回退;改过的头文件的 89 个包含者 87 -> 87 通过。启动时警告 22 -> 0;新进程登录(新人物确认)正常。
- 2026-10-10:编译警告第二轮(按驱动报告逐条修):按位 & 改逻辑运算 0 处,返回类型/原型 18 处,NPC+F_UNIQUE 的 init() 0 个,带初始化的未用局部变量 0 个,只在 #if 分支用的声明移进分支 1 个文件;改动 18 个文件,HEAD 与工作树各载入一次无回退(18 objects; HEAD PASS 14, tree PASS 14; regress 0; newly loading 0),这些文件的警告 23 -> 5。
深度功能测试(§10.7,2026-10-11):“无副作用表达式”警告复查
d/*/npc/xunbu.lpc巡捕:(: random_move() :);只造了一个函数指针就丢掉,巡捕从不走动;改为random_move();。- 改动的对象 HEAD 与工作区都能载入,无回退。
d/hangzhou/npc/mameipo.lpc媒婆:return "…嘻嘻.\n", i = 0;未满 16 岁返回 0 而非提示;拆成两句。u/lxh/emoted.lpc删去空的if (!channel_emote) {}。
深度功能测试(§10.7,2026-10-12):黑木崖老者
d/heimuya/npc/laozhe.lpcinit():残留调试行sprintf("%s \n", what);,what是对象,本驱动sprintf的%s遇对象报错,进房间时init()每次中断、招呼从不执行;删去(与 fys 同)。d/jinling/obj/y.lpc(豆腐):同时继承F_FOOD与F_LIQUID,只有液体的init()生效,永远吃不了;补一个叶子init()依次调用两者(与 fys 同)。
编译警告收尾(2026-10-12)
scripts/toolkit_fix.sh 一轮(lpc_diamonds.py 删去 38 处冗余继承)后,用 scripts/lpc_twin_port.py adopt fys tiexuejianghu --pre bf39d011b6a~1 把 fys 同一轮的修法搬过来(46 个与 fys 修前逐 token 相同的文件),再手工补两处与 fys 文字不同的头文件,能编译的文件警告清零。改动的 47 个对象 HEAD 与工作树各载入一次:HEAD PASS 25,tree PASS 28,regress 0,新载入 3(u/temp/qiaofu、u/xxy/ask、u/xxy/room/heimuya/npc/laozhe)。
include/globals.h:#define BANNED_SITES "/adm/etc/banned_sites";末尾多了分号,用到它的表达式都会多一个;;去掉后adm/daemons/band*.lpc、u/panguan/band.lpc里的同名定义与之一致,不再报重定义。include/armor.h的FINGER(指环护具)与weapon.h的同名宏相撞,#define前加#undef(同 fys)。- 孪生搬来的:
d/meizhuang/bingqiku.lpc的重复全局变量、d/zhongzhou/npc/renwu.h的重复renwu4表、daemon/skill/old/hubo.lpc的冗余继承,以及u/下几个 NPC/房间。
- 2026-10-14:新驱动(FluffOS 970d9f09)报
Float value truncated to int(#1426)。3 个文件 3 处:赋值、初始化、return 改写成to_int(...)(值不变,只是写明截断)。改动的对象新进程各载入一次,无回退(scripts/lpc_fix_float_trunc.py,KB 04 §6.10)。 - 2026-10-14(同一次重扫,手工部分,与 fys 同源同修):
- 技能文件的 int power_point()/int hard_point() 返回 1.5、1.75、2.5 之类的浮点,经 int 返回被截断,改为 float。
- feature/skill.lpc 的 query_skill() 用 power_point 作有效等级系数;学习上限、cha、skills、shengji、fenpei 用 hard_point 的平方作学习点门槛。
- 为了让这两个值进来以后结果仍是整数:query_skill() 的 point 声明为 float,乘积用 to_int();fenpei 的 hard 为 float,all = to_int(...)。否则 query_skill() 会在运行时返回浮点,fenpei 会显示带六位小数的点数。
- 玩家可见:有效等级和学习门槛按原设计的系数计算。
- 改动的 76 个对象 HEAD 与工作树各载入一次,无回退。
- 2026-10-14:4 个文件因
Type of returned value doesn't match function return type ( int vs void )整份不编译:声明为void(或没写类型)的函数却返回值,旧驱动照样把值交给调用者。调用者要用返回值的(add_action 处理函数、命令、辅助函数)改为它实际返回的类型:player_win()。新进程比对 HEAD 与工作树:4 个对象,新增载入 4,回退 0(scripts/lpc_fix_void_return.py,KB 04 §6.3)。
其他体系的属性名(2026-10-15,KB 06 §7.241 第三类,--any-file)
19 个文件(技能、绝招、兵器、书籍、区域 NPC 等)来自侠客行体系(qi/jing/neili),而本库人物是 gin/kee/sen/force:receive_damage("qi", ...) 报 伤害种类错误,query("neili") 永远为 0。按 qi→kee、jing→sen(本库学习/读书指令消耗的就是它)、neili→force、max_neili→max_force、jiali→force_factor 改名(scripts/lpc_port_es_props.py --any-file)。
治疗/疗伤的属性名(2026-10-15,KB 06 §7.241)
receive_heal()/receive_curing() 也只接受本库的种类。2 个文件(多为只调用 receive_heal/receive_curing 的药物、NPC)来自侠客行体系,按 qi→kee、jing→本库学习指令消耗的池、neili→force 改名(scripts/lpc_port_es_props.py --any-file)。
family 映射(再补)(2026-10-15,KB 05 §7.30)
mapping fam; fam = (mapping)ob->query("family");(先声明后赋值)和泥潭式的 query("family", me) 同样直接取下标:无门派的新人拜师(attempt_apprentice/recognize_apprentice)、NPC 的 greeting、房间的 valid_leave、ask_me 等报 Value being indexed is zero。2 处补上 if (!mapp(fam)) fam = ([ ]);(刚 recruit_apprentice() 之后的除外)。
空手使用兵器绝招(2026-10-15,KB 06 §7.246)
perform 指令允许直接点名招式(如 perform stick.ban),这些绝招读了 me->query_temp("weapon") 却从不检查,空手时 weapon->name() 报错(有的已先扣了内力)。在赋值后补 if (!objectp(weapon)) return notify_fail("你必须手持兵器才能使用这一招。\n");(scripts/lpc_fix_perform_weapon.py):tianyu-qijian/kuangwu。
技能名拼错(2026-10-15,KB 06 §7.249)
query_skill() 里的技能名拼错了,或用的是本库改名前的旧名;本库没有这个技能,调用永远得 0:门槛(< N 就拒绝)永远过不去,相关功夫或绝招学不了、用不了;内功互斥(> N 就拒绝)从不生效;公式里这一项一直是 0。经汉字名(提示文字或中文名词典)或纯拼写差异(_/-、少一个连字符、相邻字母颠倒)核对后,改为本库的技能名(scripts/lpc_fix_skill_typo.py):six_finger→six-finger(/daemon/class/dali/six-finger/star);yuxuan-guizheng→yuxuan-guizhen(/daemon/class/xiake/luoyan-sword/luoyan)。
存档读不出来:字符串里的换行、空行(2026-10-15,KB 03 §4.4)
data/addemoted.o:字符串里有原样的换行(save_object() 存成 \r,restore_object() 逐行读,原样的换行让字符串收不了尾),或有空行(Illegal file format),读档的对象(留言板、NPC、玩家)从空白开始。换行改写成 \r、删去空行(scripts/lpc_save_encoding.py --from-raw),驱动核对全部能读回(scripts/lpc_save_restore_check.py)。
移进不存在的巫师房间(2026-10-15,KB 06 §7.251)
用完的物品、要“离开”的 NPC、掷在空中的兵器被移进巫师的工作室(/u/wind/),本库没有这些房间。本库的 move() 用 call_other(dest, "???") 载入目的地,找不到文件就报 call_other() couldn't find object,后面的语句都不执行:被雇来打晕或杀人的李凌(d/city2/npc/liling2)办完事要离开时报错,留在原地(d/city2/npc/liling2 本身还载入不了:create() 里 carry_object() 的物品文件缺失或编译失败,见 KB 06 §7.73,另行处理)。1 个文件改为移进本库的虚空房间 VOID_OB(/obj/void),与原作把它们“停放”在巫师房间的用意相同。
NPC 带着本库没有的物品,载入失败(2026-10-15,KB 06 §7.73)
21 个文件、29 处在 create() 里 carry_object("<本库没有的文件>")->wear()(或 wield()、set_amount()):carry_object() 得 0,接着的调用报 Bad argument 1 to EFUN call_other(),NPC 根本载入不了,该有它的房间里就少了这个人。多是从别的系统搬来的 NPC 用了原系统的物品路径(最常见:/clone/misc/cloth、/clone/weapon/changjian、/d/suburb/xkx/shaolin/obj/changjian)。每处改为 { object carried_ob = carry_object(...); if (carried_ob) carried_ob->wear(); }(scripts/lpc_guard_carry_object.py):NPC 照常出现,只是不带这件东西;文件补回来(或是虚拟对象)照样会带上。载入检查:改动的文件改前能载入 0 个,改后 10 个(10 个原来载入不了),没有退步;其余 11 个另有原因(多为 set_skill() 了本库没有的武功)。
for (int i ...) 的循环变量在循环外还在用(2026-10-18,KB 04 §6.12)
当铺/商店的 do_buy() 写成 for (int i = 0; ...) if (...) break;,循环一结束又读 if (i == sizeof(inv))。FluffOS 里 for 头里声明的变量只在循环内有效,所以 Undefined variable 'i',整个房间(NPC)载入不了,当铺根本进不去。把 i 声明挪到函数开头(int i, index;),循环改成 for (i = 0; ...):std/room/hockshop.lpc。
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 载入不了,刷出它的房间也少一个人。本库有 35 个对象设了本库没有文件的武功(40 个名字,最多的是 huashan-sword、liumai-shenjian、finger)。三处都改成 return:这一门武功不给、不映射,对象照常载入,只是少了它(缺的武功本身仍是内容缺口)。抽样载入这些对象:30 个里 26 个通过,其余 4 个停在别的错误上(d/city2/npc/liling2:*No program in object '/d/city2/npc/liling2'!;d/dali/npc/duanyanqing:*No program in object '/d/dali/npc/duanyanqing'!……)。(scripts/lpc_guard_set_skill.py)
通向不存在房间的出口,按对面房间的回头出口改正(2026-10-18,KB 06 §7.257)
房间出口 "west": __DIR__"xxx" 指向的文件本库没有,玩家走过去就被卡住(笔误、改过名的房间,或者没带进档案的编号房间)。对面的房间存在、并且它相反方向的出口正好指回这个房间,说明出口原本就是通向它:/d/chengdu/dao 的 south:dadao1 → dadao2;/d/thd/nebeach2 的 northwest:foot → hill_foot。改动后每个出口都能解析到本库的文件(scripts/lpc_fix_dead_exits.py;目标在运行时本来就能载入的库——虚拟房间——不动)。
补回本库没有的基类文件(2026-10-18,KB 04 §6.15)
下面这些基类本库没有,继承它们的对象(房间、NPC、物品)整批载入不了(inherit XXX; 的宏没定义,或者 inherit "/std/…"; 的文件不在)。同系的库里有同名文件,两库有大量逐字节相同的文件(亲缘关系),所以从那边原样拷来,缺的宏补进全局头文件 include/globals.h:/feature/unique(宏 F_UNIQUE)←haiyang2,22 个对象继承它,抽样 6/10 载入;/inherit/weapon/stick(宏 STICK)←wmkj,17 个对象继承它,抽样 9/9 载入;/inherit/weapon/mace(宏 MACE)←wmkj,11 个对象继承它,抽样 10/10 载入;/std/weapon/rake(宏 RAKE)←xyj451,4 个对象继承它,抽样 4/4 载入;/inherit/weapon/bow(宏 BOW)←wmkj,1 个对象继承它,抽样 1/1 载入;/std/weapon/archery(宏 ARCHERY)←xyj451,1 个对象继承它,抽样 1/1 载入;/std/weapon/unarmed←wuhanzhan,6 个对象继承它,抽样 6/6 载入;/inherit/room/pigroom←haiyang2,4 个对象继承它,抽样 4/4 载入。每个基类补回后单独载入、再抽样载入使用它的对象,基类载不进来或者一个用户也载不进来的就撤掉(本库撤掉了它们,不再补)。(scripts/lpc_restore_bases.py)
武功名拼错的 NPC(2026-10-19,KB 06 §7.258)
set_skill("kunlun-shnfa", …)、map_skill("dodge", "shaolin-shnfa") 这样的调用把武功名拼错了:本库没有这个武功文件,有的是拼对的那个。以前这种 NPC 在 create() 里报 No such skill 载入不了;武功缺失时跳过之后它们能载入,可是少了那门武功(set_skill 被跳过,map_skill 映射不到,门派弟子用普通轻功/拳脚)。按核对过的对照表改正,共 3 处、2 个文件:tiaji-jian→taiji-jian(2 处)、sanyang_shengong→sanyang-shengong(1 处)。(scripts/lpc_fix_skill_names.py)
技能基类丢了“预备武功”那一段(2026-10-19,KB 06 §7.262)
feature/skill.lpc 有 skill_map/map_skill(),却没有预备武功(prepare_skill)这一块:变量 skill_prepare、prepare_skill()、query_skill_prepared()、query_skill_prepare()。来自 xkx 系列的 NPC 在 create() 里调用 prepare_skill("cuff", ...),于是 Undefined function prepare_skill 整个 NPC 载入不了。从同系的 xkx100 把这一块原样补回(声明加在 skill_map 后面,函数加在文件末尾),受益 NPC 2 个:d/city2/npc/liling2、d/dali/npc/huangmei。(scripts/lpc_transplant_function.py)
标准整理轮(2026-10-19,scripts/toolkit_fix.sh)
本库在新驱动下重扫,机械修复:27 个未使用的局部变量,1 处函数返回类型改成与基类一致。修后与 HEAD 逐个物件对比载入,没有退步。
找不到父类函数的 ::fn() 调用(2026-10-19,KB 06 §7.259)
/d/obj/book/kugu-1.lpc、/d/obj/book/kugu-2.lpc、/d/obj/book/kugu-3.lpc、/d/obj/fabao/kunxian-suo.lpc等共 7 个物件里写着 ::create();、::init(); 这类调用,而它们继承的基类并没有这个函数。老驱动把这种调用当成什么都不做、返回 0 的空调用,本驱动在编译时报 Unable to find the inherited function 'init'.,整个物件载入不了。这些物件的错误只有这一种(其他错误清掉之后才露出来的),逐个删掉这些调用(return ::fn(...) 改成 return 0;)。(scripts/lpc_fix_dangling_super.py)
NPC 存档缺失(2026-10-19,KB 06 §7.267)
kzznpc.h 的 NPC(客栈伙计、铁匠、裁缝、守卫等,99 个)把名字、id、武功全存在 data/npc/<名字>.o,而本档案的 data/npc/ 是空目录:restore() 之后 set_name(0, ...),enable_player() 里的 set_living_name(0) 报 Bad argument 1 to set_living_name(),物件载入失败(房间的 make_inventory 吞掉错误,商店里没有掌柜)。同一作者的姊妹档案 fys(风云三,d/ 下 5,832 个共有的 .lpc 里 5,767 个逐字节相同)带着 109 个原始存档,其中 96 个正是本库 NPC 用到的名字,已原样复制到 data/npc/。include/kzznpc.h 另加兜底:存档里没有名字或 id 时,名字取存档文件名,id 取物件文件名(扬州的 xiaohuoji 两边都没有存档)。HEAD 上 99 个 NPC 只有 5 个能载入,现在 99 个全部载入,没有退步。
区域物件的零碎修正(2026-10-19,KB 06 §7.267–§7.271)
d/thd/hall.lpc调用的留言板/u/aug/thd/thd_b改成区域里的/d/thd/thd_b,留言板的location同步改成/d/thd/hall(作者自己留在注释里的写法)
逐个物件与 HEAD 对比载入,没有退步。
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)
转换时丢掉的分号、逗号、引号或文件末尾的 },共 5 个文件,修前 HEAD 载入失败。别的库里同路径的完好副本只比这里少几个标点,按它补回(括号里是那个库):/d/baituo/npc/obj/bowl.lpc(cctx)、/d/baituo/obj/bowl.lpc(cctx)、/d/city2/npc/zhengmen.lpc(jqxz2008)。文件末尾少了 }(最后一个或两个字节丢了),补上:/u/legato/obj/skeleton.lpc(2 个)、/u/xxy/city2/npc/zhengmen.lpc(2 个)。修后与 HEAD 逐个对比载入:这 5 个物件全部载入,没有退步(scripts/lpc_restore_from_twin.py、lpc_fix_eaten_quote.py --comma、lpc_fix_eof_braces.py)。
旧驱动的类型宽松:缺省参数、无类型形参、数组初始化、class 变量(2026-10-19,KB 04 §6.19、§6.20)
原来的 MudOS 把调用少传的参数补 0、把没写类型的形参当 mixed、不检查变量的声明类型与初始值,也允许变量叫 class;这个驱动在编译时全部拒绝,整个物件载入失败。修了 3 个文件:/d/heimuya/ren.lpc、/u/mool/kid.lpc、/u/xxy/room/heimuya/ren.lpc(scripts/lpc_round_files.py 的修复轮:调用处补写 0、无类型形参补 mixed、string X = ({...}) 补星号、void 函数的返回值,以及 class 变量改名 pick_class)。逐个文件在 HEAD 和改后载入对比:这些文件里 3 个原来载入失败、现在载入,没有退步。
if (x = 常量):条件里写成赋值的比较(2026-10-20,KB 06 §7.290)
if (arg = "button" || arg = "按钮")、if (!arg || arg = "") return 0;、else if (check = 0 && tempB != ""):把 == 写成了 =,条件的值就是那个常量,分支对所有非零数和任何字符串(连 "" 都算)永远成立、对 0 永远不成立,变量还被覆盖;驱动对此没有任何警告。每一处 = 改成 ==(scripts/lpc_fix_cond_assign.py,共 8 处);其后 x == "a" && x == "b" / x == "a" || "b" 这类被 == 暴露出来的链也随之改成 || 或补全变量(/d/hainan/npc/xianhe.lpc、/d/hainan/npc/xiaohe.lpc)。改动:/d/hainan/npc/xianhe.lpc(3 处)、/d/hainan/npc/xiaohe.lpc(3 处)、/d/xxy/npc/train1.lpc(1 处)、/d/zhongzhou/yanguan.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)。
sefun cat():缺文件时 write(0) 报错(2026-10-20,KB 06 §7.297)
void cat(string file) { write(read_file(file)); }:文件不存在(压缩包没带的欢迎/公告文件,或只有运行中的 mud 才会写的日志)时 read_file() 回 0,write(0) 在本驱动里报 Bad argument 1 to receive(),调用者(登录对话、cat 指令)被中断;老驱动什么也不打印。改成 write(read_file(file) || "");(scripts/lpc_fix_cat_unchecked.py)。改动:/adm/simul_efun/file.lpc。
翻页器 start_more(read_file(...)):文件缺失时 explode(0)(2026-10-20,KB 06 §7.300)
东方故事系的翻页器 void start_more(string msg) { ... explode(msg, "\n") ... } 被这样调用:start_more(read_file(HELP_DIR + "help/topics"))、start_more(read_file(NEWS))。压缩包没带的文件使 read_file() 回 0,explode(0, ...) 在本驱动里报 Bad argument 1 to explode()(不带参数的 help 指令就是这样出错的),老驱动把 0 当空文本。在 start_more 开头加了 if (!stringp(msg)) return;(scripts/lpc_fix_start_more.py)。改动:/feature/more.lpc。
NPC 的 chat() 在 chat_msg 为空数组时下标越界(2026-10-21,KB 06 §7.334)
NPC 基类的 chat() 是 if (arrayp(msg = query(...))) { if (random(100) < chance) { rnd = random(sizeof(msg)); if (stringp(msg[rnd])) ...,不检查列表是否为空。本库现有的 NPC 文件里没有字面写成空 chat_msg 的(扫描只认 set("chat_msg", ({ })));守卫挡的是运行时才为空的列表和以后新增的 NPC。在 random(100) < chance 前面加 sizeof(msg) &&(scripts/lpc_fix_chat_empty.py;if (random(100) > chance) return 0; 的写法是 !sizeof(msg) ||)。改动:/d/obj/inherit/char/npc.lpc、/std/char/npc.lpc(共 2 个文件)。
存档里的 .c 文件名改成 .lpc(2026-10-21,KB 03 §4.2 第 9 项)
存档里写着 "/d/city/npc/wei.c" 这样的文件名;extract 时源文件已经全部改成 .lpc,而驱动对带扩展名的路径只认字面,new() / load_object() / move() 都找不到它,调用方多半把失败当成「没有这个东西」悄悄跳过。本库 68 个存档共 82 处按 scripts/lpc_fix_save_dotc.py 改成 .lpc(只改 .lpc 存在而 .c 不存在的字符串;玩家存档、备份、留言板、巫师目录和文件索引缓存不动)。改动:/data/npc/京千灵.o(8 处)、/data/npc/何红药.o(1 处)、/data/npc/刘一小.o(1 处)、/data/npc/刘麻子.o(1 处)(等共 68 个存档)。
yaoqing:#include "/data/npc/npcneed.h" 的头文件不在存档里(2026-10-21,KB 06 §7.270 的同类)
cmds/usr/yaoqing.lpc(帮会邀请 NPC 入伙的命令;tiexuejianghu 的与 fys 逐字节相同,wmkj 的是它的 qi/xiha 改写版)第四行 #include "/data/npc/npcneed.h",那是一个数据头文件(mapping npcneed = ([ "shedan gao": "蛇胆膏", ... ]),NPC 向玩家索要的东西),fys、tianxiawuxue、tybxjh、wlhd、xiyouji2003、yxcs、yxjh、zxty、zxty08nxgbb 都带着,这两个存档没有:Cannot #include /data/npc/npcneed.h、Undefined variable 'npcneed',整条命令不加载。从 fys 复制(6,473 字节)。实测 yaoqing 回答 “你没有参加任何帮会,无法邀请他人加入。”。表里的东西是 fys 世界里的物品,在这个库里能不能找到没有核对(只影响这个任务的内容,不影响命令)。没有改:xhcii 的 whotest(who 的半成品实验版,行被拼在一起)、xianlvqiyuan 的 pperform(obj 没有声明的手改副本)。
巫师命令不带参数时对 0 调用 efun(2026-10-21,KB 06 §7.336)
巫师(管理员)把命令敲成不带参数时,驱动把 0 传给字符串参数;下面的命令第一句就把这个 0 交给 efun,运行时报 Bad argument 1 to ...,这条指令从来没有用过。用 scripts/lpcc_bare.py 不登录、在一次 lpcc 求值里以 0 调用 main() 逐个确认后,由 scripts/lpc_fix_bare_arg.py 在第一处使用参数的语句前加守卫:文件自带 int help(object me) 的,守卫是 if (!arg) return help(me);(help() 定义在 main() 之后的 1 个文件补了原型 int help(object me);,否则编译报 Undefined function help)。改动(1 个文件,括号里是接住 0 的 efun):/cmds/wiz/test.lpc(present)。加载检查 HEAD 与工作树对照,没有退步。
注册到不存在函数的 add_action(2026-10-21,KB 06 §7.349)
add_action("函数", "动词") 绑定的函数,在对象本身、它包含的头文件、它继承的父类和继承它的子类里都没有定义(scripts/lpc_scan_callout_targets.py 静态解析,子类用传递闭包复核,scripts/lpc_verify_handlers.py 运行时 function_exists() 复核)。驱动从玩家最新的一条动作往回找,遇到这样的句子就报 *Function for verb 'drop' not found.,同一个动词的其他处理函数不再尝试(不是最新的一条就悄悄跳过)。删除了 13 条注册(8 个文件,scripts/lpc_fix_dead_add_action.py),动词留给别的处理函数:/d/obj/inherit/misc/fboard.lpc(do_list)、/d/taishan/npc/xiao-fan.lpc(do_buy、do_list)、/d/yandang/npc/kongmin.lpc(do_sell)、/d/yangzhou/npc/aqingsao.lpc(do_sell)、/d/yangzhou/npc/xiaofan.lpc(do_sell)、/d/zhongzhou/biwuchang.lpc(do_close、do_open、do_take)、/d/zhongzhou/biwufall.lpc(do_close、do_open、do_take)、/d/zhongzhou/npc/xiaofan.lpc(do_sell)。最多的函数名:do_sell 4 处、do_list 2 处、do_close 2 处、do_open 2 处、do_take 2 处。
缺失物品的 new() / carry_object() 调用链加了保护(2026-10-22,KB 06 §7.73 补充)
new(路径)->move(...); / carry_object(宏("x"))->wear(); 这类语句,路径指向的文件在这个压缩包里没有:new() 返回 0,->move() 在 0 上报 Bad argument 1 to EFUN call_other()。在 create() 里这个对象永远加载不了,在 reset() 里第一个缺失物品之后的刷新每次 reset 都被跳过。1 个文件里 1 处(clone_object)改成 { object new_ob = new(路径); if (new_ob) new_ob->move(...); }(scripts/lpc_guard_carry_object.py --new:路径按这个文件自己看到的宏解析,宏名冲突、虚拟对象路径一律跳过)。 对这 1 个改动文件做加载检查(HEAD 与工作区对比):HEAD 能加载 1 个,现在 1 个(新增可加载 0 个,回归 0 个)。
(: 函数 :) 指针指向对象自己没有定义的函数(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。 还剩 2 个函数没有补(item_desc 2):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/d/zhongzhou/biwuchang.lpc:look_shelf、/d/zhongzhou/biwufall.lpc:look_shelf。 另有 1 处函数体被作者整段注释掉(指针没跟着删),是有意关掉的,没动。
读不到的留言板:"/clone/board/x"->foo(); 在 create() 里报错(2026-10-22,KB 06 §7.357)
xkx 系的房间在 setup() 之后写 "/clone/board/gaibang_r"->foo(); 来加载留言板(foo() 本来就没有定义,只为了触发加载)。这个库没有这个文件,call_other() 报 *call_other() couldn't find object '/clone/board/gaibang_r',对象留在内存里、load_object() 却抛错:玩家第一次走进房间就看到错误,写在 create() 中间的还会切掉后半段。scripts/lpc_fix_missing_foo.py 把 1 条单独成行的语句(/clone/board/jail_b;/d/city2/jail.lpc)注释掉并写明原因(别的房间里同样的语句本来就是作者自己注释掉的)。证明和 45 个库的整体加载检查见 KB 06 §7.357。
(: 函数名 :) 指针指向本库没有的函数:只含这个指针的行加了注释(2026-10-22,KB 06 §7.355 补充)
inquiry / item_desc / chat_msg* 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:用到时(ask、look、NPC 闲聊)驱动抛 *Undefined lfun pointer called: 函数名,这一拍心跳的后半段被跳过。这些函数没有可以补回的来源(别的库同一路径的文件里没有,或者它还要用本库没有的东西),所以 3 个文件里 4 行只含这个指针的行("剃度" : (: ask_join :), "出家" : (: ask_join :), "shelf": (: look_shelf :),)加了注释,原文保留并写明原因,这一项当作没有这个话题 / 物品 / 闲聊条目(scripts/lpc_fix_dangling_lfun.py;#include 的文件在库里缺失的对象、指针不在整行上的写法没动)。 前提(function_exists())和加载检查(HEAD 与工作区对比,本库改动的 .lpc 文件)的结果见 KB 06 §7.355:没有一个回归。
汉字按字节切片的老写法没有换成按字符:改法名 "澄" + name[2..3]、辈分判断 name[0..1] == "澄" 等 2 处(2026-10-22,KB 06 §7.360)
原档按字节算字符串区间(一个汉字 2 字节):name[2..3] 是名字的第二个字,name[0..1] == "澄" 问名字是不是以「澄」开头。转成 UTF-8 之后,这个驱动的区间和 strlen() 都按字符算(strlen("澄观") 是 2,"澄观"[0..1] 是两个字),老算术原样留着、意思全变:拜入少林 / 武当 / 峨嵋等派的玩家被改成错误的法名(二字名 张三 变成一个字的 澄,更长的名字取到第三个字)。
本库 2 处(2 个文件):拼名字的赋值 2 处。例:name[2..3] → name[1..1](/d/emei/npc/miejue.lpc:106);name[0..1] → name[0..0](/d/emei/npc/tobebonze.h:35)。scripts/lpc_fix_gbk_slice.py 把下标按字符重算(社区的 UTF-8 版 xkx100utf8 里就是同样的写法,作对照);没有改的:截断(name = name[0..7],现在最多 8 个字,只是放宽)、ASCII 的区间(fname[0..3] == "room"、ctime(time())[4..19])和上下文看不出是汉字的区间。证明(scripts/lpcc_eval.py,bixiecanyang;其余各库是同一份文本):让澄字辈掌门 attempt_apprentice() 一个名叫「张三」的访客,HEAD 的法名是 慧,改后是 慧三;抽样 28 个库的 HEAD / 工作树加载对比 0 退步。工具不幂等([0..3] 折半得 [0..1],又是对齐区间),改过的文件记在 scripts/gbk_slice_converted.txt,不要重跑。
长度检查按字节写,旁边的提示按汉字写:6 处(2026-10-22,KB 06 §7.362)
老档的 strlen() 数字节(一个汉字 2 字节),转成 UTF-8 后它数字符:提示写「必须是 2 到 6 个中文字」的检查还是 strlen(name) < 4 || strlen(name) > 12,于是两三个字的房名、帮会名、群名、聊天室名、称号被提示自己说允许的那句话拒绝,上限却是提示的两倍;留言板的标题检查 i < 4 || i > 24 || i % 2 还会拒绝所有奇数个字的标题(post 你好吗)。本库 6 处(3 个文件):if ((strlen(name) < 4) || (strlen(name) > 12)) {(/adm/daemons/logind2.lpc:555);if ((strlen(name) < 4) || (strlen(name) > 16)) {(/d/zhongzhou/npc/hfh.lpc:39)。scripts/lpc_fix_strlen_gate.py 以提示为准:条件里每个 strlen 门槛都恰是提示所说数字的两倍才折半,存长度的变量(i = strlen(arg);)的门槛和 || i % 2 奇偶项、其后循环的 i % 2 == 0 && 一并处理;提示里有英文 / 字母 / 字节的不动。证明(scripts/lpcc_eval.py,bxsj 的留言板,求值对象继承 NPC 并重写 edit() 记录调用,command("post 标题")):HEAD 拒绝「你好」和「你好吗」、放行 23 个字的标题;改后接受前两个、拒绝第三个;shenmo 的 named.lpc invalid_new_name("张三"):HEAD 回 名字只能是2-4个中文字。,改后回 0。抽样 24 + 15 个库的 HEAD / 工作树加载对比 0 退步。
按字节写的汉字循环、茶馆猜诗和同盟频道标题(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 区间 5 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。
血条 / 表情标题按字节算显示宽度(2026-10-23,KB 06 §7.365)
老档把汉字当两字节:bar_string[0..(val * N / max) * 2 - 1] 把「格数」换成字节下标,半格血条在本驱动(按字符算区间)上会整条画满;巫师表情 edemote 的 repeat_string("─", 13 - (strlen(emotion) / 2)) 也会少减汉字宽度。scripts/lpc_fix_display_pad.py:去掉 CJK 血条 / 空白条上的 * 2(jings/qis 赋值和 blank_string3[0..(23-a)] 的 23→11 一并改),表情标题去掉 / 2;ASCII 空格的 none_string / empty_string 仍保留 * 2(一格两个空格)。本库 4 处(2 个文件)。证明(lpcc_eval.py hhsj):tribar_graph(6,9,12) 在 HEAD 画出整条 12 个■,改后为 6 个■+3 个□;麻将 strlen(tempB)/2 是两字符牌码,未改。
金毛鼠 mouse 缺分号无法加载(2026-10-27,KB 04 §6.25 Also)
open/wjw/mouse.lpc:inherit NPC 与 set_name(...) 之后每句丢了 ;() set("race"、setup()、set_leader(who) message(...))。同目录手足 haozi.lpc 完好;用 haozi 覆盖并把首 id 改回 "mouse"(fys / tiexuejianghu)。证明:HEAD 加载失败;改后加载成功,id 为 mouse/laoshu/lao shu。
wei/duanyanqing #me->move 无法加载(2026-10-27,KB 04 §6.25 Also)
踢人分支写成了 shell 风格的 #me->move("/d/city/..."),驱动报 Unknown preprocessor directive: #me,对象无法编译。改回 me->move(...)(踢出门外的提示需要这次 move)。本库改动:d/chengdu/npc/wei.lpc、d/dali/npc/duanyanqing.lpc。证明:HEAD 加载失败;改后加载成功。
wife inquiry ask_me 前置声明(2026-10-27,KB 04 §6.25 Also)
d/chengdu/npc/wife.lpc 在 create() 里写 "参茶": (: ask_me :),但 int ask_me 定义在后面,驱动报 Undefined variable 'ask_me'。在 inherit 后补 int ask_me(object me);。证明:HEAD 加载失败;改后加载成功。
铁罗汉 tie-luohan 下标丢失无法加载(2026-10-27,KB 06 §7.348 Also)
d/chengdu/obj/tie-luohan.lpc:snamei / skill_statussname / hp_statusstr 等下标括号丢失,缺 sname = keys(...),me 未赋值,另有多余的 return notify_fail 使技能复制不可达。按手足技能复制形重写 accept_fight / renewing(保留 FY 的 kee/gin/force)。证明:改前加载失败;改后加载成功。
悬空 unique::init(2026-10-27,KB 06 §7.259 Also)
d/obj/cloth/tianyi.lpc 的 unique::init();:feature/unique 无 init,驱动报 Unable to find the inherited function 'init' in file 'unique'。与邻行 cloth::init() 并存时旧 fixer 会 SKIP;本次按 in file 作用域只删 unique::init()。证明:HEAD 加载失败;改后加载成功。
yangzhou waiter vendor_goods 多余冒号(2026-10-27,KB 04 §6.25 Also)
d/yangzhou/npc/waiter.lpc 的 vendor_goods 写成 "包子": __DIR__ "obj/baozi": 1,第二个 : 非法,驱动报 syntax error, unexpected ':'。F_VENDOR 要的是名→路径(手足 aqingsao)。去掉五个货品末尾的 : 1。证明:HEAD 加载失败;改后加载成功,goods 五键。
old kuaihuo/songyang 缺右括号(2026-10-27,KB 04 §6.25 Also)
daemon/skill/old/kuaihuo-zhang.lpc、songyang-zhang.lpc:if (ob = me->query_temp("weapon") 丢了 ),后面多一个 } 把后续函数嵌进去,驱动报 unexpected L_RETURN。用同库 daemon/skill/<name>.lpc 的 valid_learn 起至文件尾覆盖。证明:HEAD 加载失败;改后加载成功。
set_max_items 补进 move(2026-10-27,KB 04 §6.16 Also)
d/obj/misc/hualan.lpc、vase.lpc 调用 set_max_items,但本库 feature/move.lpc 没有该函数(手足 sjsh / aoxiangtianji 有),物件无法编译。在 set_max_encumbrance 旁补上 max_items 默认 10 与 set_max_items / query_max_items。证明:HEAD 加载失败;改后花篮与花瓶均加载成功。
dami 误调 init_unarmed(2026-10-27,KB 04 §6.25 Also)
d/obj/food/dami.lpc 继承 ITEM+F_FOOD 却调用 init_unarmed(5)(并 #include <weapon.h>),未继承空手兵器基类,驱动报 Undefined function init_unarmed。手足 hymud 已注释该行。删掉该调用与无用的 weapon 头。证明:HEAD 加载失败;改后加载成功。
dou_peng inherit F_CLOTH(2026-10-27,KB 04 §6.25 Also)
d/thd/obj/dou_peng.lpc 写 inherit F_CLOTH / setup_cloth(),但本库 armor.h 没有 F_CLOTH(那是 dfgs2 的 feature 装甲 API),驱动报 unexpected L_IDENTIFIER。改为本库的 inherit CLOTH,保留名称与护甲 5。证明:HEAD 加载失败;改后加载成功。
force 缺 hit_ob 桩(2026-10-27,KB 06 §7.259 Also)
本库 std/force.lpc 把内功钩子叫 force_action,但 daemon/skill/old/jiuyin-shengong、xiake-shengong 仍写 ::hit_ob(...),驱动报找不到父类 hit_ob。补 hit_ob 返回 0(老驱动空父调用的值);战斗仍走 force_action。证明:HEAD 加载失败;改后两技能均加载成功。
set_encumbrance 笔误(2026-10-27,KB 04 §6.25 Also)
d/suzhou/npc/obj/test.lpc(香烟壳)写 set_encumbrance(100),本库 move 只有 set_max_encumbrance。改为后者。证明:HEAD 加载失败;改后加载成功,max=100。
book-qujing 缺 obstacle.h(2026-10-27,KB 04 §6.23 Also)
d/obj/books-nonskill/book-qujing.lpc #include "/d/qujing/obstacle.h",档案未带该头,驱动报 Cannot #include。从手足 sjsh 拷入同内容 mapping。证明:HEAD 加载失败;改后加载成功。
daemon-skill.lpc 残片改名(2026-10-27,KB 03 §4.2 item 8 Also)
open/azhou/skill/daemon-skill.lpc 仅余 xixi 六字节,无法编译;库内无引用。改名为 .txt。
fabao EXAMPLE 缺 ) 与 !(2026-10-27,KB 04 §6.25 Also)
d/obj/fabao/EXAMPLE.lpc 写 if (objectp(victim = present(target, environment())),丢了 ! 和右括号,驱动报 unexpected L_RETURN。按手足 kunxian-suo 改为 if (!objectp(victim = present(target, environment(me))))。证明:HEAD 加载失败;改后加载成功。
example/book 注释折行无法加载(2026-10-27,KB 04 §6.25 Also)
obj/example/book.lpc 的 // name of the skill 等注释被折行,下一行 the skill 成了裸标识符,驱动报 unexpected L_IDENTIFIER。用手足 sjsh 完好副本覆盖。证明:HEAD 加载失败;改后加载成功。
thd medicine 缺 DAEMON_D(2026-10-27,KB 04 §6.16 Also)
d/thd/skills/medicine.lpc 的 create() 调用 DAEMON_D->register_skill_daemon,本库无 Aug 的 daemond。删掉该行(保留 seteuid)。证明:HEAD 加载失败;改后加载成功。
深度功能测试(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… 行。