info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
本压缩包对应"金庸群侠传"(ES II 引擎)家族的"2008超豪华版"这一内容版本,md5sum 确认与本项目中的"2008加强版"(`jqxz2008`)、"2008标准版"(`jqxz2008std`)核心引擎(master、安全、登录等关键文件)逐字节相同,这支血脉还延伸到 `xiakexing3`/`xiakexing2017` 两个更远的快照;本作在门派 NPC、战斗数值配置、部分地图场景上有独立的内容调整,文件规模也是四个 2008 系版本中最大的一个。与兄弟版本一样,新角色从店小二看店的路边茶馆起步,可经中央广场的树洞暗语加入丐帮拜入左全门下,也可走白驼山使者按资质招人的另一条路线;深度测试里走通了完整的拜师→改投另一位师父的真实"叛门"流程,验证了一次真实商店交易(扣款并拿到实物),以及一次完整的战斗死亡→黑无常鬼门关→转生复活。
English
The "Deluxe" build of this project's 金庸群侠传/"Jin Yong Heroes Gathering" (ES II engine) family -- md5sum-confirmed byte-identical core engine (master, security, login, Chinese-text daemons) to sibling jqxz2008 and jqxz2008std, but the largest actual content build of the three (3,811 raw files vs. jqxz2008's 3,773), with its own sect-NPC roster and combat-number tuning (the city2 imperial-palace-gate district some earlier notes flagged as Deluxe-only is actually present in all four editions, file-count-verified -- not a genuine difference). Shares the same tea-house starting point, Beggars'-Sect passphrase-hideout join, and White Camel Mount recruiter path as its siblings.
README
内容亮点
- 以金庸武侠小说世界观为背景:少林、武当、丐帮、明教、桃花岛等门派 悉数登场,玩家从"客店"起步拜师习武、行走江湖。
在线试玩
https://mudlibs.fluffos.info/jqxz2008dlx/
管理员账号 / Admin account
- 账号 id:
fluffos密码:Mud@2026中文名:浮浮 - 权限:
(admin)(本 mudlib 的最高巫师等级),通过adm/etc/wizlist数据文件授予。
警告:Mud@2026 是本地游玩用的公开默认密码。若要正式对外开放主机,请先修改此密码(或从 wizlist 中删除该账号)。
本地运行
cd libs/jqxz2008dlx
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40085。
NOTES · 移植与修复记录
jqxz2008dlx — 金庸群侠传 (Jin Yong Heroes Gathering, deluxe)
Archive: archives/金庸群侠传2008超豪华版.rar ("Jin Yong Heroes Gathering 2008,
super deluxe edition"). Extracted mudlib root: raw/jy/ (a single top-level
jy/ directory inside the archive, same layout as archive #91). Port:
40085. Status: done (boots clean, full registration flow verified
3 times with real Chinese names, post-login look/score/quit verified
working each time).
What this is / lineage (confirmed via md5sum BEFORE doing anything else)
config.cfg's name field (GB18030-decoded: bd f0 d3 b9 c8 ba cf c0 b4
ab -> 金庸群侠传) matches the archive title exactly.
Confirmed byte-identical core engine to jqxz2008 (archive
#91, libs/jqxz2008/), checked via md5sum on the raw
archives before any conversion, per the task brief's lineage-check
instruction:
| file | md5 vs #91 | md5 vs xiakexing3(#44) |
|---|---|---|
| adm/obj/master.c | identical | identical (matches #91's own prior finding) |
| adm/single/master.c | identical | identical |
| adm/daemons/logind.c | identical | identical |
| adm/daemons/securityd.c | identical | differs (matches #91's prior finding that only securityd/config differ vs xiakexing3) |
| adm/simul_efun/chinese.c | identical | identical |
| adm/daemons/chinesed.c | identical | identical |
So this archive is confirmed to be the same underlying engine core as
#91, exactly as the task brief predicted (title-family: xiakexing3(#44),
#91, #92, #93, #94 all share the 金庸群侠传/侠客行 lineage). Per the task's
explicit instruction, all of #91's proven fixes to these byte-identical
files were ported directly rather than rediscovered from scratch (see
below) — verified line-by-line via diff against #91's already-fixed
work/ copies before applying each one, not assumed.
However, this is NOT a duplicate/near-duplicate of #91's overall content
— it's a genuinely different content snapshot on the same engine (the
same relationship as "different game version, same server software").
diff -rq of the two raw archives shows: file count differs (3773 raw
files in #91 vs 3811 here), and dozens of zone/NPC/room files differ
byte-for-byte between the two (combatd.c has different combat-formula
tuning, chard.c/updated.c/several d/ zone files differ, several
files exist only in one archive or the other e.g. clone/board/
mingjiao_b.c only here, d/mingjiao/guangmingding.c only in #91, etc).
This matches the established shujian2008/sjtx2 and
zhongjidiyu-family precedent: same engine, different content build.
Cross-check note for later archives (per task brief): archive #92
(金庸群侠传2008版.rar, being processed concurrently by a sibling agent
into libs/jqxz2008std/ at the time of this writing) and
archive #94 (金庸群侠传2015版.rar, not yet started) were NOT
cross-checked against this lib (concurrent/not-yet-processed, per the task
brief's own caveat) — whoever processes or reviews #94 next should
md5sum its adm/obj/master.c/adm/daemons/logind.c/adm/simul_efun/
chinese.c/adm/daemons/chinesed.c against both #91's and this lib's raw
copies; given the pattern held for #91 vs xiakexing3 vs this lib, there's
a real chance #94 is yet another same-engine snapshot.
Small-to-medium lib: 3,811 raw files, 3,171 .lpc/.c files sweepable by
lpcc_check.sh.
Fixes applied (with why) — ported from #91 after confirming applicability
For every fix below, the underlying file was diffed against #91's pre-fix/post-fix state first; only fixes confirmed applicable (identical buggy pattern actually present in this archive's copy) were applied. Nothing was applied blindly on lineage-assumption alone.
1. AGENTS.md §15h (is_chinese / check_legal_name — GBK byte-range
checks silently wrong under UTF-8 strings). Confirmed via diff that
adm/simul_efun/chinese.lpc and adm/daemons/logind.lpc were BYTE-FOR-
BYTE identical to #91's own pre-fix originals (not just "similar") —
ported #91's exact fix verbatim:
- chinese.lpc's is_chinese(): GBK lead-byte range (str[0] > 160 &&
str[0] < 255, strlen>=2) → CJK Unified Ideographs codepoint range
(str[0] >= 0x4e00 && str[0] <= 0x9fff, strlen>=1).
- logind.lpc's check_legal_name(): byte-count bound strlen(name) <
2 || > 12 → character-count bound < 1 || > 6; dropped the
i%2==0 && even-byte-offset gate.
- Verified working: real Chinese names "秦风", "秦风二", "秦风三"
all accepted on the first try across 3 separate registration runs.
2. AGENTS.md §15ae (private nomask command-hook breaks every
post-login command silently): feature/command.lpc's command_hook
was private nomask (same as #91); home/command.lpc's copy was
already correct (nomask only, no private) — same split as #91.
Dropped private from the feature/ copy. Verified: look and
score both work correctly post-login in all 3 test runs.
3. AGENTS.md §15t (variant 1 + variant 3, combined): combatd.lpc
DIFFERS from #91's copy in its combat-formula numbers (this is the
deluxe edition's own balance tuning), but the include/inherit-ordering
bug was present in BOTH: #include </quest/quest.h> (absolute path
inside angle brackets, never resolved by this driver's inc_open())
placed AFTER inherit F_DBASE; in source order but the file-scope
global quest_name it defines textually preceded the inherit once
included — a fatal "Illegal to inherit after defining global
variables". Fixed identically to #91: moved inherit F_DBASE; above
all #includes, and changed #include </quest/quest.h> to the quoted
absolute form #include "/quest/quest.h". Verified: score (which
needs combatd) works cleanly post-fix; before the fix this would have
thrown *No program in object '/adm/daemons/combatd'! exactly as it
did in #91.
4. The same capitalize()-on-0 robustness bug in feature/name.lpc:
byte-identical to #91's pre-fix short(int raw) fallback (capitalize
(query("id")) with no guard). Applied the identical stringp(id)
guard fix. Not independently re-triggered via a live crash this time
(the tea-house board /clone/board/kedian_b in this archive also has
no "short" set, same as #91, so this WOULD have crashed look there
without the fix — pre-emptively fixed before first boot per the task's
explicit "apply proactively before first boot" instruction, then
confirmed look works cleanly with the fix in place).
5. d/city/npc/guidao.lpc's is_killing(who) direct-call type
mismatch: byte-identical bug to #91 (is_killing(who) instead of
is_killing(who->query("id"))). Fixed identically.
6. The "tang"-family NPC template's new used as a bare variable name:
present identically in the same 7 files as #91 (d/quanzhou/npc/{tang,
tang1,tang2,tang3}.lpc, d/taishan/{tang2,tang3,xingtang}.lpc).
Renamed the local variable new → newob throughout (declaration +
both usages) in all 7 files, exactly as in #91 — the actual new(...)
efun calls are untouched.
7. AGENTS.md §15ac (bare SAVE_EXTENSION instead of
__SAVE_EXTENSION__): found in the SAME 6 files as #91 —
include/net/ftpdsupp.h, adm/daemons/network/netmail.lpc,
cmds/arch/purge.lpc, d/quanzhou/npc/tang.lpc, d/quanzhou/npc/
tang3.lpc, d/taishan/tang3.lpc. Fixed identically. Left alone
(same as #91): clone/npc/meng-zhu.lpc and u/jackyboy/TOKEN.C, which
both #define SAVE_EXTENSION ".o" locally.
8. kungfu/class/mingjiao/mingjiao.h's string-literal-adjacent-to-
macro-expansion syntax error (== HIG "明教" NOR with no +
operators): present identically. Fixed to HIG + "明教" + NOR. A
genuine divergence from #91 found here: this archive's raw copy of
kungfu/class/mingjiao/mingjiao.h ALREADY had #include <ansi.h> at
the top (confirmed via the raw, pre-conversion .c file, not just the
converted copy) — #91's raw copy was missing it and needed it added.
So only the syntax-error half of #91's two-part fix applied here; the
<ansi.h>-add half was already unnecessary. Also found and fixed the
SAME syntax bug in a SECOND, separate d/mingjiao/npc/mingjiao.h file
(different file, same bug, not mentioned in #91's notes — possibly #91
didn't have this second copy hit by its lpcc sweep, or this is new
deluxe-only content; either way it's the identical fix).
9. d/mingjiao/npc/changjinpeng.lpc's wrong absolute #include path
(#include "/kungfu/class/mingjiao/tanzhu.h" — doesn't exist; real
file is d/mingjiao/npc/tanzhu.h): present identically, fixed
identically (#include "tanzhu.h").
10. d/mingjiao/npc/{fenggongying,baiguishou}.lpc's
#include __DIR__"tanzhu.h": present identically in both files,
fixed identically to plain quoted #include "tanzhu.h".
11. d/baituo/ouyangfeng.lpc, the same two independent pre-existing
typos as #91: (a) missing semicolon after write("...") inside a
switch case 0: block; (b) object me=this-player(); (subtraction
typo for this_player()) in the LIVE inquiry_map() function. Fixed
both. Note: this file also has a second, commented-out (/* ...
*/) copy of inquiry_map() containing the SAME this-player() typo
at line 95 — left untouched since it's dead code inside a comment
block, confirmed by reading the full comment span before deciding.
12. d/shaolin/obj/shuitan.lpc: ging_cost typo for the declared
variable jing_cost: present identically at the same call site
(me->receive_damage("jing", ging_cost)). Fixed identically. Note:
this archive ALSO has a second, different shuitan.lpc at
d/shaolin/shuitan.lpc (not present in #91) — checked it separately
and confirmed it does NOT have this typo (already uses jing_cost
correctly throughout) — left untouched, no fix needed there.
13. d/mingjiao/jmqshenmu.lpc genuinely truncated in the raw archive
itself: confirmed via diff that this archive's raw .c file is
byte-identical to #91's raw .c file (both 26 lines, ending mid-
void init() { with no closing braces) — the exact same pre-existing
truncation, not a conversion artifact, not something specific to this
archive. Closed with an empty body exactly as in #91.
New fixes found in THIS archive (not part of #91's list — genuinely new
content/bugs specific to the deluxe edition's differing files)
14. d/baituo/obj/bowl.lpc and d/baituo/npc/obj/bowl.lpc (2 files,
both named bowl.lpc in different directories, same content bug):
set_name("海口大碗", "bowl") — second argument to set_name()
must be an array of id strings (every sibling file in the same
archive, e.g. d/baituo/npc/xiaoqing.lpc, correctly uses
({ "id1", "id2" })), but these two pass a bare string, which this
driver's static type checker rejects (Bad type for argument 2 of
set_name (string * vs string)) — the whole file failed to compile.
Fixed to set_name("海口大碗", ({ "bowl" }) ) in both files. Neither
file exists in #91's archive (deluxe-only content).
15. d/city2/npc/zhengmen.lpc genuinely truncated in the raw archive
itself, in a DIFFERENT way than jmqshenmu.lpc (missing closing
braces mid-function rather than mid-statement): confirmed via diff
that this archive's raw .c is byte-identical to #91's raw copy of
the SAME file (both 77 lines, valid_leave()'s nested if(dir==
"north"){ ... } else { ... } block and the function itself are never
closed) — this exact same truncation also exists, unfixed, in #91's
shipped work/ copy (confirmed via diff against #91's raw and
work directories — #91's own conversion never caught this one; it's
not in #91's NOTES.md's fix list at all). Fixed here by adding the 3
missing closing braces (traced brace depth line-by-line with a small
Python script to get the count right — first attempt under-added by
one brace, caught by a second lpcc compile and corrected). This
file is in a side zone (d/city2, the imperial-palace-gate NPC/room),
not on the tested registration/look/score path, so it wasn't a
registration blocker either way — found via the lpcc_check.sh sweep,
not a live-boot crash. Cross-check flag: since #91 has this exact
same latent bug still unfixed in its shipped work/ copy, this is
worth a follow-up patch to libs/jqxz2008/work/d/city2/
npc/zhengmen.lpc too, though that's out of scope for this archive's
own task.
- After the brace fix, the file compiles but its create() still hits
a runtime *Bad argument 1 to EFUN call_other() ... Got: int(0)
while trying to populate its "objects" mapping
(/d/city/npc/wujiang, /d/city/npc/bing — both files genuinely
exist on disk) — same shape/category as the m_weapon/luguanji.lpc
"call_other on 0" cases below (§6b-style isolated-compile artifact,
not chased further); the syntax fix alone is the meaningful
improvement (file went from "doesn't compile at all" to "compiles,
loads, one populate-step artifact identical to an established
benign category").
Confirmed NOT needed (byte-identical core files inherited the "not
needed" verdict from #91's own reading of the same file; independently
re-verified via diff that the file text is unchanged, not just assumed)
- §4 (master's lazy security-daemon recursion):
master.lpcidentical to #91's already-fixed/confirmed-clean copy (diffagainst #91'swork/adm/obj/master.lpc= empty). Same for §7, §8c, §15l, §15n/§15o, §15u, §15r, §15x, §15ao — all live inmaster.lpc/securityd.lpc, both confirmed byte-identical to #91's clean copies. - §15p (DNS/intermud daemon in preload):
adm/etc/preloadhas the same 11-entry list as #91, nonetwork/dns_master— confirmed by direct read, not inferred from lineage. - §15al (
crypt(str, 0)footgun):logind.lpcidentical to #91's already-confirmed-clean copy. - §8e (
tail()not a real efun): same single harmless hit as #91, in the same unused admin commandcmds/wiz/tail.lpc. - §15/§15b (simul_efun-based dbase architecture bug): confirmed this lib uses the same
inherit F_DBASEarchitecture as #91/xiakexing3/ rzrmud, no globalset/query/deletesimul_efuns. - Duplicate
inherit F_UNIQUE;(§91's item 7): checkedd/mingjiao/npc/{yinwushou,yinwulu,yinwufu}.lpcdirectly — only ONEinherit F_UNIQUE;in each file here, NOT duplicated in this archive (a genuine divergence from #91, where it was duplicated) — no fix needed. - A LOOKALIKE duplicate-inherit false positive, checked and confirmed harmless:
clone/misc/{roommaker,objmaker}.lpceach containinherit ITEM;/inherit ROOM;2-3 times when grepped, but on reading the actual file these are inside a@OBJ_CODE ... OBJ_CODE/@ROOM_CODE ... ROOM_CODEheredoc STRING LITERAL (a wizard tool that writes template.lpcfiles to disk for new objects/rooms) — not real compilation-unit inherits at all. Same false-positive shape as #91 (not flagged there either). - §15z (
#define nosave staticshim): none found. - Uppercase
.Cfiles: same 4 as #91, allu/jackyboy/{TOKEN, WIZ_CLOA,CLOTH1,GLASS}.C, already UTF-8, simply renamed to.lpc.
Content gaps confirmed as real archive gaps, not bugs (AGENTS.md §13)
d/mingjiao/yuan/*(9 named "yuan" NPCs — 郑七灭/王八衰/赵敏/周五输/ 吴六破/孙三毁/钱二败/赵一伤/李四摧) reference two genuinely-missing kungfu skill files (xuanyuan-arrow,liangyi-jian), same as #91.d/mingjiao/npc/monkey.lpcreferences an undefined race (走兽, "beast"), same as #91. New in this archive:d/mingjiao/gudi3.lpc/d/mingjiao/gudi4.lpc(rooms, not in #91's list) ALSO fail loading their room-embedded monkey NPC (bigmonkey) for the same undefined-race reason (走兽/走畜) — same root cause, different call sites.d/wudang/taoyuan/{tyroad4,5,6,7}.lpc: same confirmed ORPHANED early-draft duplicates of the working top-leveld/wudang/tyroad{4,5, 6,7}.lpcfiles as #91 (broken#include, no NPC spawns, unreferenced anywhere in the tree).u/liujun/quest/{leftkiller,rightkiller}.lpcreference missing skills (six-chaos-sword,stormdance) — wizard scratch quest content, same category as #91's finding (onlyleftkillerwas in #91's archive;rightkilleris new here, same shape).u/editer/tie-luohan.lpc: broken/unfinished wizard scratch draft (garbled variable namesnamei), same as #91.adm/daemons/network/*(11 files:ping_q,mudlist_a,ms,userid,pingtcp,name_server,mail_serv,netmail,telnetd,pingd,inetd): confirmed not inadm/etc/preloadand not referenced by anything outside this subdirectory — dead intermud subsystem, same category as #91 (11 here vs #91's ~16 — this deluxe build simply ships fewer of these dead files).adm/daemons/network/services/mudlist_a.lpcindependently has the SAME reserved-word bug as the tang-family (mapping new, old;) but it's unreachable dead code — not fixed, same judgement call as leavingtail()alone.home/simul_efun.lpc: same pure sweep artifact as #91 (stray backup copy in a/homesandbox, not the configured simul_efun).clone/board/*corrupted save data: 11 board.ofiles failrestore_object()with either "Illegal file format" or "Invalid utf8 string while restoring dbase" (wudang_b,xingxiu_b,tiandihui_b,towiz_b,kedian_b,bonze_b,huashan_b,gaibang_b,gaibang_r,wiz_b,taohua_b) — same class of pre-existing corrupted seed data as #91's finding (also exactly 11 boards); each board'ssetup()already wraps the failure gracefully, confirmed non-fatal via the livelooktest atkedian_b(which just starts empty, exactly as in #91).adm/daemons/chinesed.lpc'sdata/e2c_dict.orestore also fails identically to #91 (same "Illegal file format" pre-existing corrupted seed data, caught non-fatally bymaster.lpc'spreload()wrapper).d/npc/m_weapon/weapon/{m_club,m_blade,m_whip,m_sword,m_staff}.lpc: samethis_player()-is-null-during-isolated-compile §6b artifact as #91 (5 files, identical shape).- New content-gap findings, not in #91's archive:
- d/city2/obj/luguanji.lpc's carry_object(__DIR__"obj/diaopi")->
wield() fails with the same "call_other on 0" shape even though
diaopi.lpc itself compiles cleanly standalone (confirmed via a
direct isolated lpcc run) — same §6b isolated-compile-context
artifact class as the m_weapon files, just via carry_object()
instead of a direct this_player() call.
- d/city2/lilishi.lpc references /d/city/obj/tudao, which genuinely
does not exist anywhere in this archive — a real missing-content gap
(§13), not an isolated-compile artifact.
- d/xingxiu/npc/btshan.lpc references d/xingxiu/npc/ke.lpc, which
doesn't exist (§13 content gap); its sibling snake.lpc DOES exist.
- d/shaolin/cangku.lpc references d/shaolin/obj/{jitui,jiudai}.lpc,
neither of which exists (§13 content gap).
- d/shaolin/obj/{houdian,bailongdong}.lpc reference NPCs via
__DIR__"npc/..." (i.e. d/shaolin/obj/npc/...), but the actual NPC
files live one level up at d/shaolin/npc/{seng-bing3,xiang-ke}.lpc
— a genuine relative-path mismatch (the NPCs exist, just not where
these two rooms look for them). Left as a documented content/path
bug rather than fixed, since the "right" fix (change __DIR__ to
__DIR__+".." or similar) needs a judgement call about original
intent and this is a single side-zone, not on the registration path.
- d/wudang/fuzhen5.lpc references /u/fcxy/songqing.lpc, which
doesn't exist (§13 content gap; there's even a commented-out
alternate reference in the same line via CLASS_D("wudang"),
suggesting the original author knew this NPC's location was in flux).
- d/mingjiao/npc/yinsusu.lpc, d/taohua/npc/shoumu.lpc,
d/xingxiu/npc/btshan.lpc (room-self, separately from its ke.lpc
NPC-population issue above) each hit a "call_other on 0" during their
own create() — not individually root-caused further (side-zone
NPCs, not on the registration/look/score path); documented as the
same general content-gap/§6b-adjacent category.
- d/taohua/taohua_b.lpc (a bulletin board) tries to move() itself
into /tmp/jungu/dating, which doesn't exist — a genuine missing
room/zone reference (§13).
- d/huashan/map.lpc: NOT real LPC code at all — it's a plain-text
ASCII map (confirmed via file: "Unicode text... with CRLF, LF line
terminators", and its content is garbled box-drawing/tile characters,
not a program) that happens to carry a .c→.lpc extension from the
original archive; confirmed via grep that nothing in the tree ever
references d/huashan/map as an object path — dead/inert data file,
not a bug, not fixed.
- doc/build/devil.lpc, doc/efuns/shiwu.lpc: unreferenced anywhere
(grepped), genuinely-broken example/tutorial scripts under doc/
(missing semicolons, a bare do_close where a string "do_close"
was clearly intended for call_out) — never loaded in real gameplay,
left as-is per the same judgement as other wizard-scratch content.
- cmds/usr/to.lpc / cmds/wiz/to.lpc (2 files, identical bug): a
real driver-compat compile error, NOT a content gap — me->edit( (:
this_object(), ({ "do_to", me, arg }) :) ) fails with "Illegal to
use local variable in functional" (this driver forbids capturing a
local variable inside an unbound (: ... :) closure literal the way
old-style MudOS code here does it). Other ->edit() call sites in
this same lib (bboard.lpc, mailbox.lpc) pass a plain function-name
symbol and this_player()/parameter-only args and compile fine, so
this is specific to to.lpc's particular this_object(), array
calling convention. This is a real, understood bug — but it's a
non-critical wizard/player utility command (composes a multi-line
message via the line editor), not on the registration/look/score
path, and fixing it correctly would require restructuring the
closure (e.g. to a bound lambda) rather than a one-line patch, so per
AGENTS.md's "prioritize breadth over depth" policy it's documented
here as a known, real, unfixed compile bug rather than patched.
Interactive test result — full registration + post-login flow
Driver booted clean (setsid nohup ... & disown, PID 922298, launched
from libs/jqxz2008dlx/ so log/debug.log resolves
correctly per AGENTS.md §6). Zero fatal errors in log/debug.log across
the whole session — only the 2 expected non-fatal caught corrupted-
save-data errors (chinesed's e2c_dict.o, kedian_b's board data,
both documented above) and ordinary compile *warnings* ("Unused local
variable", "Illegal to declare nosave function").
Ran the full registration flow 3 separate times in 3 separate
continuous mudclient.py connections, with 3 different real Chinese
names, confirming the fix is robust and not a one-off:
1. qinfengjy (English id) → y (confirm new character) → "秦风"
→ password → confirm → accept gift stats (y) → email → gender
(m) → enters game world at 客店 → look → score → quit. All
steps succeeded; look re-rendered the room cleanly; score showed
the full character sheet (title 平民, age/gender/birthdate, 膂力/悟性/
根骨/身法 stats, 精/气 bars, 食物/饮水 bars, kill count, 潜能/实战经验);
quit saved and discononected cleanly with the "丢下一件布衣" message
(unequipped default item on quit, expected).
2. qinfengjyer → "秦风二" → same full flow, same success.
3. qinfengsan → "秦风三" → same full flow, same success (this was
the FINAL post-all-fixes confirmation run, done after the bowl.lpc/
zhengmen.lpc lpcc-sweep fixes, to make sure nothing in the late round
of fixes destabilized the core path).
Sample transcript (run 1, abbreviated to the state-changing prompts):
您的英文名字:使用 qinfengjy 这个名字将会创造一个新的人物,您确定吗(y/n)?
请输入您的高姓大名,...
您的中文名字:(accepted 秦风 first try — before §15h fix this would loop-reject forever)
请设定您的密码:
请再输入一次您的密码,以确认您没记错:
...膂力[23], 悟性[19], 根骨[19], 身法[19]
您接受这一组天赋吗?
您的电子邮件地址:
您要扮演男性(m)的角色或女性(f)的角色?
目前权限:(player)
[1;36m客店[2;37;0m -
这是一家价钱低廉的客栈,生意非常兴隆。...
这里明显的出口是 west 和 up。
/clone/board/kedian_b [ 没有任何留言 ]
店小二(Xiao er)
你上次连线是从0 on Wed Dec 31 16:00:00 1969
> 店小二用脖子上的毛巾抹了抹手,说道:这位小兄弟,请进请进。
[1;36m客店[2;37;0m - (look re-rendered cleanly)
> [1m【 平 民 】[2;37;0m普通百姓 秦风(Qinfengjy)
你是一位十四岁的男性人类,...
膂力:[ 23] 悟性:[ 19] 根骨:[ 19] 身法:[ 19]
<精> ■■■■... <气> ■■■■...
战斗攻击力 1 (+0) 战斗防御力 1 (+1)
食物:□□□... 饮水:□□□...
你到目前为止总共杀了 0 个人,其中有 0 个是其他玩家。
神: 0 潜能: 99 (1%) 实战经验: 0
> 你丢下一件布衣。
因为这样东西并不值钱,所以人们并不会注意到它的存在。
当你下次连线进来时,会从这里开始。
欢迎下次再来!Note (same test-script gotcha as #91): the English id must be fresh
letters-only each retry — a digit anywhere in the id (e.g. qinfengjy2)
gets rejected by the English-name-must-be-letters check and, since
mudclient.py sends its whole --send list regardless of prompt state,
the rejection loop consumes all the scripted follow-up sends as more id
attempts. Not a bug, just something to remember when re-testing.
lpcc sweep
Ran 3 times across the fix-iteration cycle via scripts/lpcc_check.sh:
- First sweep (after all core-engine + content fixes ported from #91, before discovering the deluxe-specific bowl.lpc/zhengmen.lpc bugs): 3104/3171 pass (97.9%).
- After fixing bowl.lpc (x2) and a first zhengmen.lpc brace attempt: 3106/3171 (97.95%) — zhengmen.lpc still failed (one brace short, caught by a Python brace-depth trace and fixed on the second attempt).
- Final: 3106/3171 pass (97.95%), same numeric pass count as the second sweep since zhengmen.lpc's remaining failure mode changed from a hard syntax error to a benign runtime "call_other on 0" content-gap artifact (documented above) rather than newly passing outright.
Remaining 65 failures were triaged by category (AGENTS.md §6b), all
confirmed via direct source reading (not guessed): 11 corrupted
pre-existing board saves, 11 dead network/intermud daemon files (not
preloaded, not referenced), ~13 genuinely missing zone/skill/race/NPC
content (mingjiao/yuan x9, monkey/gudi3/gudi4 undefined-race,
wudang/taoyuan x4 orphaned drafts, lilishi→tudao, btshan→ke,
cangku→jitui/jiudai, fuzhen5→songqing, taohua_b→missing
/tmp/jungu/dating), 3 wizard-scratch quest/tool files (u/liujun/
quest/{left,right}killer, u/editer/tie-luohan), 1 dead-code-only
reserved-word bug (network/services/mudlist_a.lpc, unreachable), 1
sweep artifact (home/simul_efun.lpc), 1 known-unfixed-efun hit
(cmds/wiz/tail.lpc, §8e), 2 non-content-gap real driver-compat bugs
left unfixed as non-critical (cmds/usr/to.lpc/cmds/wiz/to.lpc's
closure-capture error), 2 non-LPC/dead data files (d/huashan/map.lpc,
plus the 2 doc/ example scripts), 6 §6b isolated-compile-context
artifacts (5 m_weapon files + luguanji.lpc's carry_object()->
wield()), a path-mismatch pair (houdian/bailongdong → their own
npc/ subdir that doesn't exist), and zhengmen.lpc's now-syntax-clean
but still content-gap-flavored remainder. None of these affect
registration, look, or score — all confirmed via direct source
reading, not guessed.
Memory stayed healthy throughout all 3 sweeps (free -h showed ~11-19GB
available before/after each run, well clear of pressure; no other
lpcc/driver sweeps were running concurrently at sweep time).
Process notes
- Driver launched via
setsid nohup ~/src/fluffos/build-debug/src/driver config.fluffos > boot_stdout.log 2>&1 & disownfrom withinlibs/jqxz2008dlx/(required forlog/debug.logto resolve correctly, per AGENTS.md §6). Booted once, kept running through all 3 registration tests and both post-fix lpcc sweeps (the later bowl.lpc/zhengmen.lpc fixes only affect side-zones never visited by the live driver session, so no reboot was needed to validate them — thelpcc_check.shsweep independently re-reads files from disk each run). Killed by its own exact PID (922298) at the end — verified gone viaps -pandss -tlnpno longer showing port 40085 — never used a broadpkillpattern (per the explicit standing warning about other agents' concurrent drivers sharing the same command line). - Scratch files (
boot_stdout.log,lpcc_batch_raw.log) removed from the lib's top-level directory before finishing, per instructions; keptlpcc_fail.log(matches #91's own convention of keeping this one file). - Port 40085 chosen per the task brief's explicit instruction (40084 reserved for the concurrent archive #92 agent; TODO.md's own "next free port" counter said 40084 at the time this task started, so 40085 is the next port after that reservation).
2026-07-23 re-verification pass (driver rebuild + formatter + WASM)
- LPC reformat: ran
format-corpus.mjsover all ofwork/(3,171.lpcfiles) — 3,151 written, 0 already-idempotent, 20 refused (self-checked round-trip failures on messy legacy syntax, expected). - Native retest against the freshly-rebuilt driver: booted clean on port 40085, zero fatal preload errors. Full registration flow with a fresh real Chinese name ("秦风肆"/
qinfengjysi, distinct from all prior test ids on this lib) through the complete wizard (id → confirm → Chinese name → password → confirm → gift accept → email → gender) into the actual game world (客店);look,score(correct stats/combat-power/HP/potential), andquit(correct item-drop + clean save) all verified with real output, zero runtime errors in the session. No regressions from the reformat or the new driver binary. - WASM test (
scripts/wasm_client.jsagainstbuild-wasm/src): boots cleanly, same preload warnings as native. Full registration + login + look + quit all work end-to-end under WASM, same as #91/ #92 — this codebase doesn't gate login onquery_ip_number()'s format, so the documented WASM IP-check limitation doesn't apply. Same harmless cosmetic artifact as the other two variants: a fresh registration's "上次连线" timestamp shows the Unix epoch ("Wed Dec 31 16:00:00 1969") under WASM's synthetic clock — not a functional issue.
WASM-enablement pass (2026-07: loopback-allow + admin seeding)
Standard pass per AGENTS.md §1.3b/e + §1.5 (applied identically across the three jqxz2008 builds — engine files are byte-identical in this group):
adm/daemons/band.lpc:39is_banned(): short-circuitreturn 0for loopback (127.0.0.1/127.*), empty, or non-string site values before the regexp ban-list scan.logind.lpc:67'sBAN_D->is_banned(query_ip_name(ob))gate inlogon()is thereby loopback-proof (and robust against the WASMquery_ip_number()/query_ip_name()garbage-return bug).- No
uptime()startup-grace gate and no per-IP anti-flood/registration throttle exist in this lineage (checkedlogind.lpc's full input_to chain; the only other connection gate is the in-memorymad_lockadmin lockdown flag, default off — left alone).
Admin account: fluffos / Mud@2026 / 浮浮, registered through the
real native flow (id → y → Chinese name → password ×2 → gift y → email
→ gender m). Granted (admin) via adm/etc/wizlist (file was shipped
empty; now contains fluffos (admin)), which securityd.lpc reads at
create(). Verified after restart: login shows 目前权限:(admin),
update /cmds/usr/score prints 重新编译成功. Save files (must be
committed): work/data/user/f/fluffos.o, work/data/login/f/fluffos.o.
Retest: fresh registration (秦风/ceshizhe) end-to-end + look/score/quit clean; fluffos login + wizard update clean; debug.log shows only the known pre-existing corrupted-save restore errors (chinesed e2c dict / kedian board) documented above — zero new errors; test character saves removed.
Dual-mode verification pass (2026-07-24)
- Native (port 40085): fresh registration
ceshier/秦风 end-to-end into 客店 + look/score/quit all correct;fluffos/Mud@2026login shows(admin),update /cmds/usr/scoreprints 成功. debug.log: only the two documented pre-existing corrupted-save restore errors (caught by the lib's handler) — zero new errors. Driver killed by exact PID. - WASM (build-wasm with query_ip_number/resolve fixes): fresh registration
wasmceshi/秦风 end-to-end + look/score/quit all correct; second invocation:fluffosadmin login(admin)+update成功. Verdict: native OK + wasm OK. No fixes needed this pass. Test character saves removed; fluffos.o timestamp churn reverted.
深度功能测试(§10.7,本轮):移植同引擎兄弟档案 jqxz2008 已确认的 4 个 bug
这份档案自己的 README 已经说明和"2008 加强版"(jqxz2008)、"2008 标
准版"(jqxz2008std)是完全相同的服务端引擎核心,只在门派 NPC、战斗
数值、部分地图内容上有独立调整。jqxz2008 自己已经做过一轮扎实的
§10.7 深度测试并记录了 4 个真实 bug——既然引擎核心相同,这轮直接逐一
核对这些 bug 是否也存在于 jqxz2008dlx(而不是重新从零排查),四个
全部确认存在且未修复:
1. adm/daemons/chinesed.lpc(§7.7:损坏存档数据把全局 mapping 清
零)。 data/e2c_dict.o 是损坏的二进制垃圾数据(不是合法的 mapping
字面量),create() 原本是 seteuid(getuid()); restore();——
restore() 抛出的运行时错误没有在 create() 内被捕获,会让 create()
在那一行直接中止,mapping dict 被清零。第一次真正用到
chinese()/to_chinese() 的地方(战斗/技能提示大量使用)就会崩溃。
修法和 jqxz2008 完全一致:catch(restore()); if (!mapp(dict)) dict
= ([]);——单独加 mapp() 判断而不加 catch() 是不够的,因为不加
catch() 那一行代码根本不会被执行到。
2. adm/daemons/combatd.lpc/cmds/std/kill.lpc/cmds/skill/{bai,
apprentice}.lpc(§7.11:缺失的 /log/nosave/ 目录让 write_file()
静默中止一个多步骤清理函数)。 work/log/nosave/ 目录在这份档案里
同样不存在。最严重的是 combatd.lpc 的 killer_reward()——这个函数
在每一次死亡时都会跑到,中间不加保护地 write_file("/log/nosave/
KILLRECORD", ...),一旦目录不存在就会抛出未捕获异常,让 die() 在
那一行永久中止:角色的死亡清理(尸体、鬼魂状态、移动到死亡场景)全部
不会执行,角色变成"活着但气血精气归零"的破损状态,而且这个崩溃会在
之后的每一次 heart_beat() 都重新触发一次,变成死循环。用真实驱动
让测试角色(沈十)被"欧阳克"这个 NPC 杀死做了实测验证:你死了 →
干净地进入"鬼门关"死亡场景,NPC"白无常"正常打招呼,全程 debug.log
保持空白(十秒以上的心跳观察也没有延迟复现)。修法沿用 jqxz2008 已
验证过的 assure_file()(这份档案自己的 adm/simul_efun/file.lpc 里
已经有这个函数),在全部四处 write_file("/log/nosave/...", ...) 调
用前各加一行 assure_file(...);顺手也给 bai.lpc/apprentice.lpc
里的 read_file() 结果加了 stringp() 判断(避免 atoi(0))。
3. cmds/skill/bai.lpc/cmds/skill/apprentice.lpc(一处括号位置
错误,把 == 比较写进了 query() 的参数列表内)。 这两个完全相同
的档案里都有:
if (((string)me->query("family/master_id" == "feng qingyang")) || ...)== 比较被夹在 query(...) 的参数括号内,所以传给 query() 的实际
是一个布尔/整数值(永远是 0),不是想要的属性名字符串——这个用来检
测"是否从风清扬门下叛出"的分支永远不可能触发。已改成先呼叫
query("family/master_id"),再拿它的返回值和字符串比较(和同一档案
里其它所有正确写法一致)。触发条件很窄(角色确实拜风清扬为师后又叛
出),本轮没有专门构造这个场景做实测,但代码结构本身已经明确证明这
是笔误而非设计判断。
以上四个 bug 全部对应到既有的 AGENTS.md §7.7/§7.11/§7.9 类别,不是新 分类,只是在同一引擎的另一个具体档案上再确认一次——这也进一步印证了 "共享同一底层引擎的多个档案(内容版本不同)值得直接核对已知 bug 列 表,而不是每份都从零排查"这条经验(和这个会话里 NT/nitan 家族的 §7.78 系列发现是同一个模式)。
未继续测试的部分
时间关系,除了已经验证的注册、战斗、死亡流程外,没有测试拜师
(bai/apprentice)本身、购物、以及触发风清扬叛出这个罕见分支——
bai/apprentice 的两处修复已经通过代码对照(逐字节对比两个档案确
认改动一致)验证,未做额外的实机拜师测试。
补充发现(来自对同引擎兄弟档案 jqxz2008std 的深度测试):第 5 个 bug,§8.9 食物/饮水初始化检查错了对象
adm/daemons/logind.lpc 的 enter_world() 里:
if (!user->query("food") && !user->query("water") && ob->query("age") == 14) {age 是角色本身(user)的属性,不是登录物件(ob)的属性——
ob->query("age") 永远是 0,这个分支从来没有真正执行过,每个新
角色的食物/饮水从创建起就永远是空的(score 显示空白状态条),静
默、无报错。已改成 user->query("age") == 14,用真实驱动重新注册
验证过(沈叁),score 正确显示食物/饮水两条状态全满。这个 bug 在
标准版(jqxz2008std)先发现,确认加强版/超豪华版/标准版三份档案
里 logind.lpc 这一行逐字节相同,一并同步修复。
WASM 修复摘要(迁移自 meta.json 的 group_note)
同一引擎,不同内容构建版本。
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 19 处命中,已删除多余的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)已经在更早一
轮(引用注释里的"AGENTS.md #15w")正确修复过,管理员账号
(fluffos/Mud@2026,adm/etc/wizlist 已有 fluffos (admin))
也已经用真实注册流程创建并提交过,本轮只发现并修复了 log_file()
一处(和同引擎兄弟档案 jqxz2008 同一形状)。
发现并修复的 PROGRAMMING bug
1. log_file()(adm/simul_efun/file.lpc)完全没有 assure_file()
保护(AGENTS.md §7.11-class 的又一确认实例):注册/登录本身只
写 log_file("USAGE", ...)(无子目录,本来就存在),不受影响,
但 nosave/CRASHES/nosave/PURGE/nosave/CALL_PLAYER 等管理指
令路径会在首次使用时未捕获抛出。已补上
assure_file(LOG_DIR + file);(含前向声明)。
Proactive checks(无需改动)
win_times修复确认存在且正确:d/city2/npc/refereew.lpc:176; 姊妹文件u/wind/refereew.lpc:176/refereew2.lpc:184同样已修。- 未发现
message()simul_efun 包装函数——不适用 message()-missing-varargs 这一类 bug。 - 本次未观察到
jqxz2008那份档案独有的data/e2c_dict.o存档损 坏问题——开机 preload 阶段和log/debug.log均干净,两份档案虽 然同引擎但各自数据文件的完整性状态并不共享。
实测过程
用已提交的 fluffos/Mud@2026 登录,score 确认"目前权限:
(admin)",update /adm/simul_efun/file(就是本轮改过的文件)确认
可正常重新编译。log/debug.log 时间戳全程未变化(Aug 5,早于本
次会话,且文件本身为空),确认无新增未捕获运行期错误。登录本身产
生的存档时间戳类微小 diff(data/{login,user}/f/fluffos.o 的
last_on 字段)已用 git checkout 撤销,不提交。驱动最终按精确
PID kill,ps -p 确认已退出。
(data/{login,user}/s/shenten.o 是此前会话遗留的未提交测试存档
——Aug 5 mtime,早于本次会话,未受本轮任何操作影响,未触碰。)
§7.100 扫描修复(ROOM 基类多余 replace_program())
#define ROOM "/inherit/room/room":删除 826 处多余的、独立成行的
replace_program(ROOM);(保留 inherit ROOM;)。本库自带的房间
建造工具 clone/misc/roommaker.lpc(与 jqxz2008/jqxz2008std
同一血统的"寒山寺"结构)"造一间空房间"的 heredoc 模板本来就干净,
但"克隆我所在的房间"命令的字符串拼接模板把同一枚多余的
replace_program(ROOM); 烤进了每一个新克隆的房间,已同步修正。已
用 build-debug 驱动干净启动验证(0 个新增编译错误,端口正常监
听);未做完整 §10.7 深度游玩测试。
§7.30 uninitialized-mapping accessor sweep (2026-08-20)
Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage
bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2
via round-four testing): 4 accessor(s) in this file returned a raw
never-initialized mapping instance variable (defaults to int 0,
not ([]), until first assigned), crashing any unguarded
keys()/sizeof()/indexing caller for a fresh/untrained character.
Fixed at the accessor level (mapp(x) ? x : ([])) per the documented
remedy. Verified via lpcc --batch static compile check only (not a
live boot) as part of a large mechanical sweep; not individually
functionally re-tested live on this lib.
深度功能测试(§10.7,round four):三个此前未实机测试的分支全部实测
补齐本档案自己 NOTES.md 之前标记的"未继续测试的部分"——拜师
(bai/apprentice)本身、商店购买、风清扬弟子叛出——三项全部用真
实驱动、真实指令实机验证,全程 debug.log 保持空白(无新增
error:/crash)。测试角色:shensi(沈肆,男,登记密码已略去不
记录)。
标准检查清单快速确认(应已修复,仅确认不重新排查):
- §7.90(eval-cost):档案顶层
config.fluffos(实际开机用的 config,不是work/config.cfg)maximum evaluation cost已经是5000000,work/config.cfg里较低的300000是未使用的 legacy 副本。确认无需改动。 - §7.100(
ROOM多余replace_program()):已在更早一轮修复 (见上方章节),本轮未重新排查。 - §7.111(
standard_trace()对error["object"]==0崩溃):adm/obj/master.lpc/adm/single/master.lpc都已经是objectp(error["object"]) ? file_name(error["object"]) : "(driver)"的正确写法。确认无需改动。 - §7.112(
death_stage()重入保护):d/death/npc/ {newgargoyle,wgargoyle,bgargoyle}.lpc、d/shaolin/npc/yu-zu2.lpc逐一读过全部death_stage()函数体,每一个提前return的分支 (目标消失、非鬼魂反被杀、最终转生)都正确地先delete_temp("death_stage_active")再返回,没有发现遗漏的分支。 确认无需改动。 - §7.79(裸 2 参数
addn()/addn_temp()):全档案work/树内零命中,不适用。 - §7.108(踢出重登录后指令失效):
clone/user/user.lpc:110的reconnect()已经无条件在最前面enable_commands();,修复已 存在。 - §7.30(
feature/skill.lpc未初始化 mapping accessor):见上 一节,本轮 corpus 扫描已覆盖。 combatd.lpc的bounce除零 bug:grep -n 'bounce' adm/daemons/combatd.lpc零命中,这份档案的combatd.lpc根本没 有bounce变量,不适用。
1. 拜师(bai/apprentice)——已实机验证,多次成功,无崩溃,
师承/头衔正确更新:测试角色先在 /d/huashan/buwei2 对入门弟子路
线的岳不群 bai yue(门槛低:shen≥1000+query_int()≥25),成功
——score 确认"华山派第十四代弟子",师父岳不群;随后移动到 /d/
huashan/houshan 对风清扬 bai feng(门槛高:剑法/紫霞神功/身法/
文学等技能≥130~150、shen≥100000、query_int()≥41、随机 kar
检定),管理员用 call shensi->set(...)/set_skill(...) 赋予测试
角色对应属性/技能后(任务允许的"管理员捷径进场景,真实指令走真实
代码"手法),成功——score 确认"华山派第十三代弟子",师父风清
扬。全程无崩溃,family_name/master_id/头衔(第N代弟子)均正确
更新,验证了本档案自己 NOTES.md 里之前只做过代码对照、从未实机触
发过的 bai.lpc/apprentice.lpc 两处修复(§7.11 assure_file()
+ stringp() 判断、§7.9 类的括号错位修复)在真实驱动下运行正确。
2. 商店购买——已实机验证,价格扣除+实物到手全部正确:d/city/
zahuopu.lpc(杂货铺)用 list/buy 两个指令,NPC 杨永福
(d/city/npc/yang.lpc)用 F_DEALER 混入。管理员 clone /clone/
money/coin + call coin->set_amount(500) + give coin to shensi
(任务允许的"clone+give 该档案真实货币物件"标准手法,give 需要
admin 和目标角色在同一房间才能成功,一开始漏了 goto 导致"这里没
有这个活人",补上 goto /d/city/zahuopu 后成功)给测试角色 500 文
铜板;list 确认价目表,buy budai(麻布袋,标价一两白银=100文,
注意商品的 buy 用的是 set_name() 里的别名"budai",不是档案名
"mabudai",用错名字会被 do_buy() 正确拒绝为"你想买什么?"而非崩
溃)购买成功,i 确认物品到手(麻布袋)且找零正确(四两白银,
500-100=400=4两,数学验证一致)。无编译错误/运行时崩溃/debug.log
报错。
(过程中发现一个值得记录、但确认是设计而非 bug 的机制:feature/
dealer.lpc 的 do_buy() 第一行就有 if ((fam =
this_player()->query("family")) && fam["family_name"] == "丐帮")
return notify_fail("你是个穷叫化,买什麽东西!\n");——丐帮弟子被
硬性禁止在普通商店购物,这正是任务说明里"non-beggar test
character"这条要求的真正来源。测试角色因为先做风清扬叛出测试而暂
时加入了丐帮,商店测试前特意再实机 bai yue 一次把门派切回华山
派,才能通过这道设计关卡;notify_fail 走的是正常拒绝路径,没有
任何错误信号,按本 session 的 scope 纪律不作修改。)
3. 风清扬弟子叛出——已验证,真实触发,命中此前只做过代码对照的
apprentice.lpc 修复分支:读 cmds/skill/apprentice.lpc(第 55
行 if ((object)ob->query_temp("pending/recruit") == me),本档案
自己 NOTES.md 记录的括号错位修复处)确认触发条件——目标已经对我方
pending/recruit(即目标已经用 recruit 指令点名收我为徒、只等
我回拜),且我方当前 family/family_name 与目标不同才会触发"背叛
师门"文案;若我方当前 family/master_id == "feng qingyang",还会
额外命中一段读写 /log/nosave/FENG 计数文件的分支(本档案自己
NOTES.md 记录的另一处 §7.11 assure_file() 修复,此前也只做过代
码对照,从未实机跑过)。
实测路径:先用管理员 possess feng+recruit shensi(这一步之所
以能立即完成拜师而不是仅仅"挂起",是因为测试角色此前有一次被风清
扬本人 attempt_apprentice() 正常拒绝的 bai feng 尝试——即使被
拒绝,apprentice.lpc 也已经在拒绝之前无条件地把
pending/apprentice 挂在了测试角色身上,recruit 指令检测到这个
挂起状态会直接完成拜师,不需要再走 attempt_apprentice() 的门槛
检查),确认测试角色 family/master_id 变为 "feng qingyang"
(score 显示"华山派第十三代弟子",师父风清扬)。随后管理员移动测
试角色到 /d/gaibang/inhole,possess zuo(左全,丐帮),执行
recruit shensi——这次确认真正挂起(左全对测试角色还没有
pending/apprentice)——输出"你想要收沈肆为弟子",正确进入
recruit.lpc 的"挂起"分支而非"立即完成"分支。退出附身后,测试角色
真实执行 bai zuo:命中目标分支,输出"风清扬现在共有0个徒弟。"
(确认 /log/nosave/FENG 被 assure_file() 正确建立且未崩溃,文
件确认内容为"0")、"你决定背叛师门,改投入左全门下!!"、"恭喜您成
为丐帮的第二十代弟子。"——family_name 从"华山派"变为"丐帮",
master_id 从风清扬变为左全,score 确认师承信息正确更新。全程
debug.log 保持空白。这是本档案自己 NOTES.md 明确记录"逐字节代码
对照验证、未做实机测试"的两处修复(括号错位分支本身 + 嵌套的 FENG
计数器写入)第一次真正被驱动执行到,确认运行时行为完全符合预期,
没有发现新 bug。
测试方法论备注(供后续同引擎档案参考):recruit 指令的
"挂起 pending/recruit" 分支只有在目标此前没有已经对我方挂起
pending/apprentice 时才会触发;如果顺序反过来(我方已经因为一次
被拒绝的 bai 挂起了 pending/apprentice),管理员 possess 目
标后执行 recruit 会直接完成拜师(走 recruit.lpc 自己的分支),
不会经过 apprentice.lpc 里那处待验证的 pending/recruit 分支
——本轮测试头几次尝试就踩到了这个顺序问题(用 call
feng->recruit_apprentice(shensi) 直接注入也不可行,call 指令的
参数解析器只认字面量/带引号字符串,裸标识符 "shensi" 会被当成字符
串传入触发 call_other() couldn't find object 'shensi' 运行时报
错——这是 call 这个管理指令自身已知的语法限制,不是 mudlib
bug),最终靠"先用一次会被拒绝的真实 bai(这一步真实无害地挂起
了 pending/apprentice),再用管理员 recruit 补上"的顺序绕开,
才干净地复现了目标分支。
驱动进程按精确 PID 结束(kill -TERM,确认 cwd 匹配后操作),测试
角色 shensi/管理员 fluffos 的存档增量(师承变化、FENG 计数器
从 0 到 1、fluffos.o 的正常时间戳类增量)按既有约定一并提交,未
触碰此前会话遗留、未提交的 shenten.o。
深度功能测试(§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-05)— tail() simul_efun
scripts/lpc_add_tail.py --apply: cmds/wiz/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)— 房间列出的物件缺档时房间照常加载
房间基类 inherit/room/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-05)— 巫师留言板存档 data/board/*.o.gz
巫师留言板 wiz_b / towiz_b 以 .o.gz 存档(1996 年的帖子)。本机驱动 restore_object() 优先读 .o.gz,而留言板用 save_object(file) 写明文 .o,所以本机上新帖每次重启都退回旧快照;网页版驱动没有 zlib,只读 .o,而归档自带的 .o 是读不出的二进制。.gz 内容为 GB18030(转码时没被处理),转成 UTF-8 写成 .o,替换归档里那个读不出的二进制 .o;towiz_b 原文有 4 个残字节,转为替换符。删除 .o.gz(KB 01)。用 lpcc 载入留言板核对条数(jqxz2008:wiz_b 47 条、towiz_b 115 条)。
深度功能测试(§10.7,2026-10-07)— 空的 if (current_water == 0) {}
3 个房间的 valid_leave() 里有一行什么也不做的 if (current_water == 0) {}(编译警告 Expression has no side effects),删去,行为不变:d/xingxiu/nanjiang2.lpc、d/xingxiu/nanjiang3.lpc、d/xingxiu/shanjiao.lpc。
深度功能测试(§10.7,2026-10-07)— 编译警告整理
scripts/lpc_warnings.py jqxz2008dlx --fix 加 scripts/lpc_fix_no_effect.py --apply,共改动 257 个 .lpc 和 10 个 .h(多为删去未用的局部变量)。HEAD 与工作树分别加载(新进程):245 -> 245 通过,无回退;改过的头文件的 60 个包含者 60 -> 60 通过。启动时警告 17 -> 0;新进程登录(输入名字)正常。
- 2026-10-10:编译警告第二轮(按驱动报告逐条修):按位 & 改逻辑运算 0 处,返回类型/原型 6 处,NPC+F_UNIQUE 的 init() 0 个,带初始化的未用局部变量 1 个,只在 #if 分支用的声明移进分支 0 个文件;改动 6 个文件,HEAD 与工作树各载入一次无回退(6 objects; HEAD PASS 6, tree PASS 6; regress 0; newly loading 0),这些文件的警告 6 -> 0。
- 2026-10-10(续):第二轮编译警告整理(
lpc_fix_unused_init.py)删掉了只在不启用的#if分支里用到的局部变量声明(如include/net/ftpdsupp.h中#ifdef GUEST_WIZARD_FTP分支的file),启用该选项时会编译失败;声明已放回所用的分支里,工具已改为跳过这种情况(交给lpc_move_decl.py)。
编译警告收尾(2026-10-13)
scripts/toolkit_fix.sh 一轮去掉 18 处多余继承;include/net/ftpdconf.h 把 VALID_READ、VALID_WRITE 定为 1,覆盖 ftpd.h 的 0,先 #undef(同 xiakexing2017),行为不变。能编译的文件警告清零;改动的 18 个对象在 HEAD 与工作树各载入一次:HEAD PASS 17,tree PASS 17,regress 0。
- 2026-10-14:2 个存档文件(留言板 2 个;
data/board/gaibang_b.o,data/board/tiandi_b.o)还是原档案的 GBK 编码,没有转成 UTF-8,restore_object()报Invalid utf8 string后对象以空数据启动(表情守护进程没有表情、留言板没有帖子、玩家无法载入)。scripts/lpc_save_encoding.py逐个按 GB18030 解码,结果按存档格式解析通过才写回(KB 03 §4)。
无门派玩家的 family 映射(2026-10-15,KB 05 §7.30 第三种)
mapping fam = ob->query("family"); 之后直接 fam["family_name"]:没有门派(新人或叛师后)的玩家在学习、练功、拜师、进入门派房间时报 Value being indexed is zero,而不是作者写好的提示。5 处在声明行加上 if (!mapp(fam)) fam = ([ ]);(scripts/lpc_fix_family_guard.py)。
其他体系的属性名(2026-10-15,KB 06 §7.241 第三类,--any-file)
另有 3 个文件(绝招、状态、物品、NPC 等,不限于 kungfu/skill)来自 gin/kee/sen/force 体系,同样按 kee→qi、gin/sen→jing、force→neili 改名(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。5 处补上 if (!mapp(fam)) fam = ([ ]);(刚 recruit_apprentice() 之后的除外)。
技能名拼错(2026-10-15,KB 06 §7.249)
query_skill() 里的技能名拼错了,或用的是本库改名前的旧名;本库没有这个技能,调用永远得 0:门槛(< N 就拒绝)永远过不去,相关功夫或绝招学不了、用不了;内功互斥(> N 就拒绝)从不生效;公式里这一项一直是 0。经汉字名(提示文字或中文名词典)或纯拼写差异(_/-、少一个连字符、相邻字母颠倒)核对后,改为本库的技能名(scripts/lpc_fix_skill_typo.py):beimin-shengong→beiming-shengong(hamagong、honghua-shengong、huagong-dafa、huntian-qigong、hunyuan-yiqi、kuihua-xinfa 等 16 个文件);mizongxinfa→mizong-xinfa(longxiang/fanchang);qiankundanuoyi→qiankun-danuoyi(/cmds/std/nuoyi)。
family 映射内联取下标(2026-10-15,KB 05 §7.30)
ob->query("family")["master_name"]、me->query("family")["family_name"](泥潭式为 query("family", ob)[...])直接对门派映射取下标:没有门派的人(新玩家、叛师者、大多数 NPC)在 NPC 的打招呼和问话、绝招的门派判断、房间的 valid_leave 里报 Value being indexed is zero,而不是得到拒绝。7 处(6 个文件)改为 dbase 路径查询 query("family/master_name"):有门派时值相同,没有时得 0;原有的判断照常生效(scripts/lpc_fix_family_index.py)。给映射赋值的写法未动。
NPC 带着本库没有的物品,载入失败(2026-10-15,KB 06 §7.73)
5 个文件、5 处在 create() 里 carry_object("<本库没有的文件>")->wear()(或 wield()、set_amount()):carry_object() 得 0,接着的调用报 Bad argument 1 to EFUN call_other(),NPC 根本载入不了,该有它的房间里就少了这个人。多是从别的系统搬来的 NPC 用了原系统的物品路径(最常见:/d/city/obj/tudao、/d/city2/obj/obj/diaopi、/d/yanziwu/npc/obj/green_cloth)。每处改为 { object carried_ob = carry_object(...); if (carried_ob) carried_ob->wear(); }(scripts/lpc_guard_carry_object.py):NPC 照常出现,只是不带这件东西;文件补回来(或是虚拟对象)照样会带上。载入检查:改动的文件改前能载入 0 个,改后 4 个(4 个原来载入不了),没有退步;其余 1 个另有原因(多为 set_skill() 了本库没有的武功)。
留言板存档损坏时 setup() 不再抛错(2026-10-18)
data/board/*.o 里有几个是外来的二进制数据(以 ?inh 开头,restore_object() 报 Illegal file format - 1)。inherit/misc/bboard.lpc 的 setup() 里 restore() 直接抛,留言板对象(连带创建它的客店房间,比如 d/city/kedian)载入失败。改成 catch(restore());,留言板以空板启动(xkx2017 的同一个文件早就是这样写的)。上面「存档损坏」那一条里说的“setup() 已经包住了”并不准确。
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 载入不了,刷出它的房间也少一个人。本库有 9 个对象设了本库没有文件的武功(2 个名字,最多的是 xuanyuan-arrow、liangyi-jian)。三处都改成 return:这一门武功不给、不映射,对象照常载入,只是少了它(缺的武功本身仍是内容缺口)。抽样载入这些对象:9 个里 9 个通过。(scripts/lpc_guard_set_skill.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 映射不到,门派弟子用普通轻功/拳脚)。按核对过的对照表改正,共 5 处、4 个文件:xinxiu-duzhang→xingxiu-duzhang(2 处)、tiaji-jian→taiji-jian(2 处)、jinyin-baiguzhao→jiuyin-baiguzhao(1 处)。(scripts/lpc_fix_skill_names.py)
全局头文件丢了 1 个宏(2026-10-19,KB 04 §6.16)
/include/globals.h 里没有定义 MAILDIR,用到它们的物件(名单里 1 个)编译时报 Undefined variable/Undefined function,整个物件载入不了(编译器在第一个未定义的名字上停下,后面的错误和警告都看不到)。同系的库在各自的头文件里都有这几行:照其中和本库共有文件最多的那个库,原样补到 /include/globals.h 最后一个 #define 之后,宏体里出现的路径在本库里都存在。名单里的物件除了这几个宏之外还有别的错误,暂时仍载入不了。(scripts/lpc_restore_defines.py)
标准整理轮(2026-10-19,scripts/toolkit_fix.sh)
本库在新驱动下重扫,机械修复:9 处浮点数赋给 int 的地方改成 to_int()。修后与 HEAD 逐个物件对比载入,没有退步。另有 7 处浮点数赋值要手工改(lpc_fix_float_hooks.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 文件。
技能的 power_point() 返回类型(2026-10-19,KB 04 §6.10)
kungfu/skill/ 下 6 个技能的 int power_point(object me) { return 1.5; } 返回的是浮点数,新驱动按 int 声明截成 1。声明改成 float,值回到设计的 1.1、1.5…。这个库里读 power_point() 的只有遗留的 combatd.b(二进制,不加载),combatd.lpc 不调用,所以对运行没有别的影响。
玩家打造兵器模板没有打造者时(2026-10-19,KB 06 §7.275)
/d/npc/m_weapon/weapon/m_blade.lpc、/d/npc/m_weapon/weapon/m_club.lpc、/d/npc/m_weapon/weapon/m_staff.lpc、/d/npc/m_weapon/weapon/m_sword.lpc、/d/npc/m_weapon/weapon/m_whip.lpc(共 5 个)的 create() 开头 me = this_player(); 之后无条件读 me->query("weapon/name") 等打造数据。房间刷新时没有人在场(me 为 0),或者 NPC 在别的 NPC 的命令环境里 carry_object() 这个模板(NPC 的 weapon 属性是文件名字符串),旧驱动里读出来是 0 或字符串,switch 照样落到 default;新驱动报 Bad argument 1 to EFUN call_other() / Bad argument 1 to switch,NPC 和它所在的房间载入不了(--walk 普查里一个玩家走进房间就触发)。在 //读入数据 之后加 if (!me || !mapp(me->query("weapon"))) { setup(); return; }:没有打造者就留一个没有名字的空模板,玩家打造的流程不变。
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)。改动:/d/mingjiao/shanmen.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 整个指令就编译不过,to 这类先开编辑器、再回调自己的指令因此从未能用。改成 (: call_other, this_object(), "do_to", me, arg :)(参数在建立指针时绑定,编辑器再把输入的文字接在最后,do_to(me, arg, text) 收到全文;scripts/lpc_fix_functional_locals.py)。改动:/cmds/usr/to.lpc(1 处)、/cmds/wiz/to.lpc(1 处)。
call_out_info() 的每一项只有 3 个元素(2026-10-20,KB 06 §7.287)
驱动返回的是 ({ 物件, 函数, 延迟 }),不带 call_out 的参数,旧代码读第 4 项 info[i][3](callouts 指令、calloutd、cod 工具)一读就报 Array index out of bounds,指令从第一行起什么也打印不出来。改为 (sizeof(info[i]) > 3 ? info[i][3] : 0)(scripts/lpc_fix_callout_info.py)。改动:/cmds/arch/callouts.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。
存档里的乱码文件:restore_object() 报 Illegal file format(2026-10-20,KB 06 §7.316)
存档里有一批数据文件是乱码:开头是 ?adm、?inh、?clo、?obj(#/adm/… 的第一个字节被换成了 ?),后面是随机字节,没有任何驱动读得了。adm/daemons/chinesed 在预载时 restore() 读 data/e2c_dict.o,首次登录时起始房间的留言板 /clone/board/kedian_b 读 data/board/*_b.o;restore_object() 对不是文本的文件抛 Illegal file format,调用处的 catch()(KB 06 §7.255)保住了房间和精灵,但本库 master 的 error_handler() 把调用栈返回给驱动,每次启动和首次登录都在控制台打印一次或两次 错误讯息被拦截。现在共用的 feature/save.lpc 的 restore() 先读文件第一个字节,不是 # 就返回 0(读被 master 拒绝时 read_bytes() 返回 0,仍由 restore_object() 决定,和以前一样);留言板和字典从空开始,第一次 save() 写出合法文件,乱码文件原样留在树里。实测:启动和登录都没有报错,已保存的角色重新连线照常加载。
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) ||)。改动:/inherit/char/npc.lpc(共 1 个文件)。
存档里的 .c 文件名改成 .lpc(2026-10-21,KB 03 §4.2 第 9 项)
存档里写着 "/d/city/npc/wei.c" 这样的文件名;extract 时源文件已经全部改成 .lpc,而驱动对带扩展名的路径只认字面,new() / load_object() / move() 都找不到它,调用方多半把失败当成「没有这个东西」悄悄跳过。本库 3 个存档共 6 处按 scripts/lpc_fix_save_dotc.py 改成 .lpc(只改 .lpc 存在而 .c 不存在的字符串;玩家存档、备份、留言板、巫师目录和文件索引缓存不动)。改动:/d/shaolin/npc/obj/kat.o(1 处)、/d/shaolin/obj/kat.o(1 处)、/d/shenlong/obj/lxlx.o(4 处)(共 3 个存档)。
巫师命令不带参数时对 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 与工作树对照,没有退步。
blockade / recover:data/keep 不存在,解封之后世界仍然锁着(2026-10-21,KB 06 §7.340)
管理员扫描里 blockade 报 Error copying file from /data/user/f/fluffos.o to /data/keep/fluffos, Error: No such file or directory,随后的 recover 在第一个 cp() 上死于 */data/keep/fluffos: lstat failed,来不及执行最后的 LOGIN_D->set_madlock(0):封锁解不开。data/keep/ 是运行时目录,git 克隆里没有空目录。blockade 在第一次写之前 if (file_size("/data/keep") != -2) mkdir("/data/keep");(mkdir() 失败答 0,不抛错),recover 对没有保存档的玩家 if (file_size(src) < 0) continue;,其余照常恢复、照常解锁(scripts/lpc_fix_keep_dir.py,hy5 上实测:没有保存档时 recover 答“时空解封完毕”,blockade 建出 data/keep 并保存,recover 取回并删除)。改动(2 个文件):/cmds/adm/recover.lpc、/cmds/arch/blockade.lpc。
注册到不存在函数的 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.,同一个动词的其他处理函数不再尝试(不是最新的一条就悄悄跳过)。删除了 2 条注册(2 个文件,scripts/lpc_fix_dead_add_action.py),动词留给别的处理函数:/inherit/misc/fboard.lpc(do_list)、/kungfu/class/gumu/yangguo.lpc(do_qiecuo)。最多的函数名:do_list 1 处、do_qiecuo 1 处。
对象路径里的 ..:new(__DIR__ "../obj/x") 报 Read access denied(2026-10-22,KB 06 §7.351)
__DIR__ 是当前文件所在目录(带结尾斜杠),__DIR__ "../obj/x" 就是 /d/zhiye/npc/../obj/x;驱动的 legal_path() 不接受带 .. 的路径,new() / load_object() 直接抛 *Read access denied.(实测,find_object() 对它答 0)。走库自己的 carry_object() / 房间 objects 表的路径,库的基类会先规范化,能用;直接把路径交给 new() / clone_object() / load_object() / move() 的不行,调用到那一步才报错。改成规范化后的绝对路径(scripts/lpc_fix_dotdot_dir.py --direct):/d/wudang/npc/xiaocui.lpc(__DIR__ "../obj/nuerxiang" → "/d/wudang/obj/nuerxiang")。
(: 函数 :) 指针指向对象自己没有定义的函数(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。 还剩 1 个函数没有补(inquiry 1):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/d/huashan/npc/teller.lpc:tell_fortune。
(: 函数名 :) 指针指向本库没有的函数:只含这个指针的行加了注释(2026-10-22,KB 06 §7.355 补充)
inquiry / item_desc / chat_msg* 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:用到时(ask、look、NPC 闲聊)驱动抛 *Undefined lfun pointer called: 函数名,这一拍心跳的后半段被跳过。这些函数没有可以补回的来源(别的库同一路径的文件里没有,或者它还要用本库没有的东西),所以 1 个文件里 1 行只含这个指针的行("算命": (: tell_fortune :),)加了注释,原文保留并写明原因,这一项当作没有这个话题 / 物品 / 闲聊条目(scripts/lpc_fix_dangling_lfun.py;#include 的文件在库里缺失的对象、指针不在整行上的写法没动)。 前提(function_exists())和加载检查(HEAD 与工作区对比,本库改动的 .lpc 文件)的结果见 KB 06 §7.355:没有一个回归。
汉字按字节切片的老写法没有换成按字符:改法名 "澄" + name[2..3]、辈分判断 name[0..1] == "澄" 等 18 处(2026-10-22,KB 06 §7.360)
原档按字节算字符串区间(一个汉字 2 字节):name[2..3] 是名字的第二个字,name[0..1] == "澄" 问名字是不是以「澄」开头。转成 UTF-8 之后,这个驱动的区间和 strlen() 都按字符算(strlen("澄观") 是 2,"澄观"[0..1] 是两个字),老算术原样留着、意思全变:拜入少林 / 武当 / 峨嵋等派的玩家被改成错误的法名(二字名 张三 变成一个字的 澄,更长的名字取到第三个字);各派掌门的辈分判断(name[0..1] == "澄")永远不成立。
本库 18 处(13 个文件):拼名字的赋值 10 处、与汉字常量比较 8 处。例:name[0..1] → name[0..0](/kungfu/class/emei/kong.lpc:134);name[2..3] → name[1..1](/kungfu/class/shaolin/cheng.h:155);name[0..1] == "慧" → name[0..0] == "慧"(/kungfu/class/shaolin/cheng.h:139)。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,不要重跑。
黑木崖脚下的老者:init() 里留着调试语句,每个走进 /d/heimuya/road1 的人都触发运行时错误(2026-10-22,KB 06 §7.361)
d/heimuya/npc/laozhe.lpc 的 init() 在 ::init() 之后有 what = new(__DIR__ "obj/yancao"); sprintf("%s aaa\n", what);:调试遗留,%s 收字符串或数字、不收对象,于是 (s)printf(): Incorrect argument to type %s. (arg: 0) 每次有人进入乱石坡都抛一次,后面的 call_out("greeting", ...) 永远不执行,老者不再搭话(还每次白克隆一个烟草)。两行都注释掉(同系的 haiyang2 / hy / hy5 / cctx / fqyy2 早就注释了)。证明:scripts/lpc_reach_census.py xiakexing2017 --load --walk(一个普通 NPC 访客走进每个加载成功的房间):HEAD 336/337,改后 337/337。
按字节写的汉字循环、茶馆猜诗和同盟频道标题(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 区间 1 个文件。证明(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 是两字符牌码,未改。
doc/build devil 丢分号/粘连 inherit(2026-10-27,KB 04 §6.25 Also)
doc/build/devil.lpc(建档示例倭寇)被格式化弄坏:inherit NPC void create() 粘在一起,语句之间的 ; 全丢,还有嵌套坏掉的 set("con", set("con", 10)。按原意重写成带 setup() 的完好 NPC(原 /obj/blade、/obj/cloth 在多数库不存在,示例里去掉携带以免 create 炸)。证明:HEAD 加载失败;改后加载成功。