info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
本游戏自称 火影(英文 Naruto),`master.lpc`/`simul_efun.lpc` 等文件头把底层引擎归功于 Annihilator(muds.net)的 "Neolith 0.0.2"(2000 年9月),是 "ES2"(东方故事Ⅱ)引擎家族的一员,与本项目中的武汉站、雪影奇缘同宗,血缘上也与 es1_win、esI、kxkj、haiyang2 等更远支相关。以日本动漫《火影忍者》为题材(`globals.h` 里甚至留有一行被注释掉的 `MUD_NAME`"火影忍者"),登录界面带有取材自台湾站点的精美 ANSI 彩色 ASCII 艺术 Logo。存档里的忍术/查克拉技能与装备模板库其实相当可观,但内容并不完整:实机测试确认这份快照里实际可通行的房间只有巫师公会设施(公告板、举报处、议事厅等 5 间),并未随附可探索的忍者村/江湖地图,`START_ROOM` 直接硬编码指向巫师公会——更像是引擎与框架的技术快照,而非完整的关卡内容包。
English
The game calls itself Huoying (Naruto); its master.lpc/simul_efun.lpc/chinese.lpc headers credit the underlying engine to Annihilator (muds.net) as "Neolith 0.0.2" (09/07/2000), placing it in the same ES II (Eastern Story II) engine family as this project's wuhanzhan (A Chinese Odyssey) and yueyingqiyuan (Moon Love Story), and more distantly es1_win/esI/kxkj/haiyang2. Themed after the Naruto anime -- globals.h even carries a commented-out MUD_NAME of "火影忍者" ("Fire Shadow Ninja") -- with a fairly elaborate ANSI color ASCII-art login banner sourced from a Taiwanese site. Content is honestly thin: the archive carries a substantial jutsu/chakra-skill/equipment template library, but live testing found only five navigable rooms, all wizard-guild facilities (noticeboard, complaints desk, meeting hall) -- START_ROOM is hardcoded straight to the wizard guild, with no explorable ninja-village map shipped in this snapshot.
README
内容亮点
- 归属 ES2/Neolith 谱系,属性、装备、门派、任务框架沿用武侠类 MUD 的基本结构,但设定与用语都改成了忍者世界的风格。
- 存档内的武功/道具/NPC 模板库其实相当可观(忍术、查克拉相关技能、 装备分类一应俱全),但经深度实机测试确认:本快照实际可通行的房间 仅有巫师公会设施(公告板、举报处、议事厅等 5 个房间),并未随附 可探索的正式忍者村/江湖地图——
START_ROOM就硬编码指向巫师公会。 换言之,这份存档更像是引擎/框架的技术快照,而非完整关卡内容包。
在线试玩
https://mudlibs.fluffos.info/huoying/
管理员账号 / Admin account
- 账号 id:
fluffos密码:Mud@2026中文名:浮浮 - 权限:
(admin)(本 mudlib 的最高巫师等级),通过adm/etc/wizlist数据文件授予(新增一行fluffos (admin),与原有的acme (admin)并列)。
警告:Mud@2026 是本地游玩用的公开默认密码。若要正式对外开放主机,请先修改此密码(或从 wizlist 中删除该账号)。
本地运行
cd libs/huoying
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40059。
NOTES · 移植与修复记录
huoying — 火影 / "Naruto" (ES2 mudlib, Annihilator lineage)
Archive: 火影.rar (archive #65; byte-identical duplicate 火影 (1).rar
already flagged in AGENTS.md's Duplicate archives table and NOT
re-processed). Port: 40059. Status: done (boots clean, full
registration flow verified end-to-end with a real Chinese name including
reconnect + quit, lpcc sweep 98.1% pass).
What this is
config.cfg's own name field says 火影 (matches the archive title),
and the header comment identifies the underlying engine: Neolith 0.0.2
by Annihilator (09/07/2000) — this is the ES2 mudlib lineage
(Annihilator, muds.net), the same family as wuhanzhan/kxkj/
yueyingqiyuan (archives #53/#54/#58) — confirmed via master.lpc's own
copyright header ("This program is a part of ES2 mudlib... Annihilator
<[email protected]>") repeated verbatim across master.lpc,
simul_efun.lpc, chinese.lpc, logind.lpc, securityd.lpc,
virtuald.lpc, etc.
include/globals.h has #define MUD_NAME_INTERMUD "Naruto",
#define MUD_NAME_ABBR "Naruto", and a commented-out
#define MUD_NAME "火影忍者" ("Naruto" literally, "Fire Shadow Ninja") —
confirms the lib is genuinely Naruto-themed, not just coincidentally named.
The archive's own included 火影说明.txt (author's readme, by "AKAI",
2006.09) says it was found on a Taiwan site and redistributed because it
looks especially good over ZMUD's ANSI-art client — this checks out at
connect time: the MOTD includes real, quite elaborate ANSI-art banner
graphics (a large multi-color logo) that render correctly once terminal
codes pass through untouched.
Root: raw/火影/ (one level, not nested further). config.cfg:
master file : /adm/obj/master, simulated efun file : /adm/obj/simul_efun,
mudlib directory : .. Modest-sized archive: 572 raw files, 466 real LPC
(.c→.lpc) source files — no bundled driver source, no mega-lib
concerns.
Conversion (convert_lib.sh)
Clean pass, no manual stragglers found afterward (verified with the
standard file -b re-scan for .lpc/.h files, and grep for .c"
leftovers/directories literally named *.c — zero hits on both). Numbers:
572 files total, 471 converted GB18030→UTF-8, 70 already-UTF-8, 0 lossy,
31 skipped-binary (real binaries: mudos.exe, .b binary dumps, a few
.o genuinely-binary saves). 466 .lpc files after rename, 168 literal
.c" refs fixed automatically, 42 files touched by static→nosave.
New encoding gotcha found here: a config file can be genuinely
MIXED GBK+BIG5, and GB18030 decode does NOT error on the BIG5 bytes
config.cfg's name : 火影 line is correctly GBK (bb f0 d3 b0 decodes
to 火影 under GBK/GB18030) — but the file's own header comment block
(# Neolith 0.0.2 ..., # Annihilator (09/07/2000)) and its
default fail message/default error message values are genuinely
BIG5-encoded (Traditional Chinese), left over from the original
Taiwan author and apparently never touched by whoever re-encoded the rest
of the lib's .lpc source to Simplified/GBK for redistribution. Confirmed
byte-for-byte with Python (b'\xab\xfc\xa5O...'.decode('big5') →
"指令錯誤,請輸入 help cmds 了解各項指令用法..." — coherent Traditional
Chinese; the same bytes under GBK decode to visible mojibake:
"���O岿粇�A叫块�J help cmds..."). The dangerous part: iconv -f
GB18030 does NOT throw an error on these BIG5 byte sequences — GBK/BIG5
byte-ranges overlap enough that the bytes decode to *some* valid-looking
(but wrong) codepoints, so convert_lib.sh's lossy-conversion detection
(which only catches genuine decode *failures*) can't catch this at all.
Manually identified the 4 affected lines (grep -na '[^\x00-\x7F]'
config.cfg to enumerate every non-ASCII line, then spot-decoded each
candidate both ways and compared for coherent output) and rebuilt
config.fluffos decoding those specific lines with BIG5 and everything
else with GB18030. Low real-world impact here (only affects 2 cosmetic
player-facing messages plus code comments, not gameplay), but this is a
new variant worth watching for on any other Taiwan-origin ES2/Neolith-family
lib: a per-line mixed-encoding file where the wrong codec still "succeeds"
silently is a strictly harder case than the previously-documented
whole-file BIG5-fallback scenario, since there's no error to trigger a
retry — only a manual read-through catches it. Did NOT find this issue
anywhere in the actual .lpc source tree (spot-checked several files,
including long room/item descriptions — all read as coherent Simplified
Chinese, i.e. genuinely GBK throughout).
Fixes applied (mudlib-side, before/during first boot)
1. AGENTS.md §4 — master.lpc's valid_read/valid_write lazy
load_object(SECURITY_D) recursion, confirmed via lpcc before ever
attempting a full driver boot
The original code already wrapped the lazy load in catch():
nosave int valid_read( string file, mixed user, string func ) {
object ob;
if( !catch(ob = load_object(SECURITY_D)) && objectp(ob) )
return (int)SECURITY_D->valid_read(file, user, func);
return 1;
}This looked like it should already be safe (§4's catalog entry describes
the UNGUARDED variant as the bug) — but running lpcc on logind.lpc
(which pulls in the full chain including securityd.lpc) produced exactly
§4's signature symptom anyway: a flood of Too deep recursion. /
Error in error handler: *Too deep recursion. rooted at
master.lpc:292 (the valid_read line). Root cause is exactly as §4
describes: catch() only protects the control flow of *that specific
call* — it does nothing to prevent the driver's own error-reporting path
from calling back into valid_read/valid_write (to check permission to
write the error/log) as a brand-new outer call, which retries the same
disallowed load_object() again, ad infinitum, overflowing the C++ call
stack regardless of the inner catch(). Lesson for future libs: don't
assume a catch()-wrapped load_object(SECURITY_D) is automatically safe
just because it superficially matches the "fixed" shape — always verify
with a real lpcc compile of a file that pulls in the daemon chain (not
just eyeballing the source) before concluding §4 doesn't apply.
Fix: added the standard re-entrancy-flag guard (loading_security_d) to
both valid_write and valid_read in master.lpc, matching the shape
already in the catalog. Re-ran lpcc on logind.lpc afterward: zero
recursion, zero errors, full compile chain succeeds (confirmed by reading
the complete lpcc output, not just grepping for "error").
2. AGENTS.md §15h — is_chinese() GBK-byte-range check and
check_legal_name()'s byte-count bounds/loop, in adm/simul_efun/chinese.lpc
and adm/daemons/logind.lpc
is_chinese(str): wasstrlen(str)>=2 && str[0] > 160(GBK lead-byte range check, requiring 2+ bytes = 1+ full GBK char). Fixed tostrlen(str)>=1 && str[0] >= 0x4e00 && str[0] <= 0x9fff(CJK Unified Ideographs codepoint range, requiring 1+ character).check_legal_name()'s bound: wasstrlen(name) < 2 || strlen(name) > 12(2..12 bytes = 1..6 GBK chars) — halved to< 1 || > 6to match what the message text already said ("必须是 1 到 6 个中文字" — "must be 1 to 6 Chinese characters").- The per-character validity loop: was
if( i%2==0 && !is_chinese(name[i..<0]) )— thei%2==0landed on alternating BYTE offsets to catch each GBK character's lead byte; dropped it entirely since every index is already one full character under UTF-8, so now every position is checked. - A third, previously-uncatalogued §15h-family variant found in this same function:
if( name[i..i+1]==" " )(rejecting a literal fullwidth-space character in the name) —name[i..i+1]was a 2-BYTE-wide GBK slice (matching the 2-byte encoding of " " itself) but is now a 2-CHARACTER slice being compared against a 1-character literal, so the comparison can never be true again — the check silently stopped firing entirely (not "checking the wrong range" like the other §15h cases, but "never triggers at all"). Fixed by narrowing toname[i..i](single character), restoring the intended behavior. Worth adding to the general §15h checklist: any fixed-width substring compared against a literal for equality (not just sliding-window "is this Chinese" checks) needs the same byte-width→char-width correction.
Verified via the interactive registration test below (a real 2-character
name "秦风" and a 3-character name "王小虎" both accepted correctly and
advanced past check_legal_name to world entry) — not just a standalone
lpcc-dumped function check.
3. Port-hardcoded master.lpc connect() dispatch via MUD_PORT —
new gotcha, not previously in the catalog
master.lpc's connect(int port) switches on the literal incoming port
number (case MUD_PORT: ... case HTTP_PORT: ...), where MUD_PORT/
HTTP_PORT are #defined in include/globals.h to the archive's
*original* hardcoded ports (8000/8015). Since every lib in this batch
gets assigned a different sequential port (here, 40059) that has no
relationship to the archive's original port numbers, the switch fell
through with no matching case and no default, so connect() implicitly
returned nothing — every single connection attempt was rejected outright
at the TCP layer with Can not accept connection from ... due to error in
connect()., before logon() or any LPC login code ever ran at all (no
compile error, no debug.log error beyond that one line — this is a classic
"boots clean, but every real connection instantly fails" trap, easy to
miss if you only check for compile errors and the "Accepting telnet
connections" banner). Fixed by updating MUD_PORT in globals.h from
8000 to 40059 to match config.fluffos's actual port number. Check
for this on any other lib in this ES2/Neolith lineage (or any lib whose
master.lpc connect() dispatches on a literal port number) — grep
master.lpc for connect(int port) and a switch/if on the parameter,
and cross-check every compared constant against the lib's actual assigned
port before the first real client-connect test (a bare lpcc sweep or a
telnet-less driver boot will NOT catch this, since connect() is only
exercised by a real incoming socket).
4. AGENTS.md §15w — log_error() broadcasting compile *warnings* to
players as scary "compile-time error" messages
master.lpc's log_error(file, message) (bound to APPLY_LOG_ERROR)
unconditionally did if(this_player(1)) efun::write("编译时段错误﹕" +
message) for every message reaching it — and this driver funnels every
soft compile *warning* (Illegal to declare nosave function, Unused
local variable, Unknown #pragma, ignored, etc. — all harmless,
expected noise from this batch's static→nosave conversion and old
#pragmas) through that same apply, not just genuine fatal errors like
the original author assumed. Reproduced directly: the very first
registration test (character "秦风") spammed dozens of 编译时段错误:...
warning: ... lines to the connecting player as soon as gender selection
triggered the lazy compile of /std/char.lpc and its ~30-file inherit
chain (/feature/char/*.lpc, /std/room.lpc, /std/bboard.lpc, etc.).
Fixed by gating the player-facing efun::write on the message NOT
containing the substring "warning:" (kept the unconditional file-log
write for every message, warnings included). Re-ran the identical
registration test afterward (fresh id "qiufeng") — zero spam, debug.log
still cleanly split into a normal boot-time trace, not evidence the
warnings simply stopped occurring.
5. A pre-existing single-file typo, world/eq/leg/gai.lpc (§10-family:
missing/misplaced string-literal quote)
set_name(HIG"阿盖\"NOR, ({ "gai" }) ); has a stray backslash directly
before the closing quote of the "阿盖" name literal — confirmed present
byte-for-byte in the RAW pre-conversion archive too (5c 22 right after
the GBK bytes for "盖"), so this is a genuine original-author typo, not
conversion fallout. The escaped quote makes the string literal swallow
everything up to the next real unescaped quote, producing a cascade of
confusing "Illegal character 0xNN" errors on later, perfectly-valid UTF-8
Chinese text further down the same file (once the parser is desynced from
being "inside a string" when it shouldn't be, subsequent real string
literals get read as raw source tokens instead). Fixed by removing the
stray backslash: set_name(HIG"阿盖"NOR, ({ "gai" }) );. Low-impact (a
single leg-armor item, "阿盖" — an obvious Naruto/Rock Lee/"Gai-sensei"
reference given the theme), but a one-line fix worth taking since it was
trivial and matches a cataloged pattern.
Checked and confirmed NOT applicable (verified by reading the actual
source, not assumed)
- §15l (
master.lpc create()destructingSIMUL_EFUN_OB/MASTER_OBas an old bootstrap trick):master.lpc create()here is justwrite(...)— nodestruct/efun::destruct()call anywhere in it. Confirmed by reading the full file. - §15n (custom
securityd.lpc'svalid_readACL blocking the driver's own compile-timeload_object/includeaccess):securityd.lpchere HAS a genuinely custom ACL (trusted_read/exclude_readmappings keyed by directory+status), the exact shape §15n warns about — but the full registration-through-world-entry test (which lazily touches dozens of never-preloaded files:/std/char.lpcand its ~30-file inherit chain,/adm/daemons/questd.lpc,/world/area/wizard/*, etc.) completed with ZERO "Read access denied" errors anywhere indebug.log. Read throughvalid_read's logic to understand why it didn't bite here: the very first check isif( !(euid = geteuid(user)) ) return 0— but by the time any of these lazy compiles are triggered (mid-registration, well afterget_id/seteuid(arg)has already run), the connection object already has a real euid set, and none ofexclude_read's directories (/arch,/adm,/data,/u,/log) matched anything actually touched during registration+first-room-entry (/std,/feature,/world,/obj,/daemonare NOT inexclude_readat all). Confirmed empirically, not just by inspection — worth re-checking per-lib since a different exclude-read table shape (e.g. one that also excludes/std//feature) could still hit this. - §15o (
master.lpcmissingget_include_path()breaking mid-connection#includes):master.lpchas noget_include_path()defined at all — the exact gap §15o describes. But the full registration+world-entry test never hit aCannot #include <file>error (checkeddebug.logspecifically for this string — zero hits), and thelpccsweep (which exercises the entire.lpctree, including many files never touched by registration) shows only 2 genuinely-missing-header failures (ansi2.h,path.h— see below), neither of which is an include-path resolution issue (both files are simply absent from the archive, quoted or not). Concluded this lib doesn't need theget_include_path()insurance patch — its#includes are already quote-form/local enough not to need it. Not adding the patch preemptively per the task's "verify per-lib" instruction, since it wasn't needed here. - §8e (
tailnot a real efun): present (cmds/wiz/tail.lpc,tail(file)), fails in thelpccsweep exactly as expected — an unused admin command, not reachable from simul_efun or preload context. Left as a known/documented failure per precedent (lib #1's identical case), not fixed. - §8f (
TYPE * a, b;comma-list array-modifier bug): one superficial match (cmds/wiz/mudlist.lpc:43: string* args, mud_name;) butmud_nameis never used as an array anywhere in the file (grepped all uses) — a false positive, not the real bug; left alone. - §15b (more "called everywhere, never defined" simul_efun globals): none of the previously-catalogued names (
remove_ansi,noansi_strlen,B2G,db_affected,clr_ansi,chinese_number[this lib defines its own, delegating toCHINESE_D],changed_match_path,query_bandwide,query_shadowed) appear anywhere in this lib's source at all (grepped each name individually) — none of that family applies here. - §15t (absolute-path angle-bracket includes /
..-relative includes / inherit-after-globals ordering): grepped for#include <[^>]*/(a slash inside angle brackets, indicating an absolute-looking path) and#include ".*\.\./"— zero hits of either shape anywhere in the tree. Not applicable. - §15v (
LONELY_IMPROVED-style always-on flag gating deadefun::X()calls): grepped forLONELY_IMPROVEDand the wholecount_add/count_mul/... bignum-wrapper family — zero hits. This is a Neolith/ES2-lineage lib, not the NT/nitan/Lonely lineage §15v documents; not applicable. - §15u (dormant phone-home/self-destruct license check): grepped
securityd.lpc/master.lpcforrm/shutdown/mass-deletion patterns gated on an opaque check — found nothing beyond ordinary, legitimate admin commands (cmds/adm/shutdown.lpcis a normal wizard command, requires explicit invocation). Not applicable. - §8g (N identical lpcc failures sharing one root cause): the 9 remaining
lpccfailures (after thegai.lpcfix) are all INDEPENDENT single-file issues (each a different root cause — see below), not one shared dependency producing a cascade. Confirmed by reading every failure's actual error text individually (only 149 lines total inlpcc_fail.log, small enough to read in full rather than pattern-match).
adm/etc/preload — DNS/intermud daemon (§15p)
Already had /adm/daemons/network/dns_master commented out in the
ORIGINAL archive (#/adm/daemons/network/dns_master — the # was already
there pre-conversion, not something this pass added). Preload list left
as-is (11 active entries: securityd, virtuald, logind, cmd_d, chinesed,
emoted, aliasd, fingerd, channeld, natured, enterd) — boots in a few
seconds, no hang observed.
Boot + registration-flow verification
Booted ~/src/fluffos/build-debug/src/driver config.fluffos from
libs/huoying/ (per AGENTS.md §6 — log directory is CWD-relative;
created libs/huoying/log/ as a sibling of config.fluffos, separate
from libs/huoying/work/log/). Clean boot: all 11 preload daemons load
with only cosmetic warnings (Unknown #pragma, ignored, Unused local
variable, Illegal to declare nosave function — all expected/harmless
per §3/§15w), Accepting telnet connections on 0.0.0.0:40059. /
Initializations complete., zero fatal errors in debug.log.
Full registration-flow transcript (via scripts/mudclient.py, one
continuous connection), reading adm/daemons/logind.lpc's actual
input_to callback chain first (logon→get_id→confirm_id→
new_password→confirm_password→get_email→get_gender→get_name→
enter_world) rather than inferring it from prompt text — no hidden
pre-id gate found in this lib (unlike §15q/precedent libs):
--send "qiufeng" # English id (get_id, 3-10 lowercase letters)
--send "y" # confirm new-character creation (confirm_id)
--send "test12345" # password (new_password, >=5 chars)
--send "test12345" # password confirmation (confirm_password)
--send "[email protected]" # email (get_email, format-checked)
--send "f" # gender (get_gender)
--send "秦风" # REAL Chinese name (get_name -> check_legal_name)
--send "look"
--send "quit"Result: prompts advanced correctly at every step; "秦风" (2 real Chinese
characters) was accepted by check_legal_name (no rejection message),
immediately followed by 目前权限:(player) (confirms make_body/enter_world
executed, not a silent stall) and then the full MOTD banner, the game's
opening-room description ("巫师神殿" — Wizard's Temple), and
你连线进入这个世界。 ("You have connected into this world.") — full
success into actual gameplay, not just past the name prompt. Zero
"编译时段错误"/error text of any kind reached the player after the
§15w fix (compare against the FIRST test run, before that fix, which did
show ~40 lines of warning-spam during this exact same step).
Second pass, reconnect + quit (separate connection, same character):
--send "qiufeng"
--send "test12345" # get_passwd (existing save found)
--send "look"
--send "quit"Result: 重新连线完毕。 ("Reconnect complete") → room re-displayed
correctly (with a wandering NPC, "龙虾", visibly present) →
你重新连线回到这个世界。 → look re-displayed the room → quit →
欢迎下次再来!你(qiufeng) 离开游戏。 (clean disconnect message). Confirms
save/restore and the full session lifecycle work, not just first-time
character creation.
Third pass with a fresh id and a 3-character Chinese name ("王小虎") also succeeded identically, confirming the fix isn't a fluke tied to one specific name length.
lpcc sweep
scripts/lpcc_check.sh libs/huoying/config.fluffos libs/huoying/work:
457/466 pass (98.1%). Remaining 9 failures, all read individually
(not just pattern-matched) and confirmed independent, pre-existing archive
gaps/incompatibilities rather than conversion bugs — left unfixed per the
"breadth over depth" policy, documented here as known issues:
/world/area/wizard/hockshopand/adm/daemons/questd(+/cmds/usr/quest, which sharesquestd'screate()/save file) — both fail withrestore_object(): Illegal file format/Illegal mapping formatwhile restoring pre-existing seed save data (world/area/wizard/hockshop.o,data/questd.o). Confirmed the save files are NOT corrupted by our conversion (byte-identical Chinese text either way; the raw archive's own.ofiles already contain literal embedded raw newline bytes inside quoted string values — e.g. a "long" room description ending mid-value with a real\r\nbefore its closing quote — which appears to be a legitimate but unusual old-MudOS save_object() quirk that this FluffOS build'srestore_object()parser doesn't tolerate the same way). Tried stripping\rfrom the affected file as a quick experiment; did not fix it, so left as-is rather than chase further — neither file is on the registration/first-room path (confirmed by the successful interactive test above, which never touches the hockshop room or the quest system), so this doesn't block the "done" bar. Worth a deeper look if anyone picks up quest-system work on this lib specifically./world/item/mj.lpc(Cannot #include ansi2.h),/world/item/gobang.lpc(Cannot #include path.h),/obj/water.lpc(inherit F_DRINK;whereF_DRINKis never#defined anywhere) — all three genuinely missing dependencies in the ORIGINAL raw archive (confirmed:ansi2.h,path.h, and anyF_DRINKdefinition are all absent fromraw/火影/too, not a conversion artifact) — a mahjong item, a Go/gobang board item, and a water-drink object the original author apparently never finished wiring up. Per AGENTS.md §13, a real archive gap, not a bug to fix./cmds/usr/version.lpc(Undefined variable '__DRIVER__') and/cmds/adm/socket.lpc(Undefined function dump_socket_status) — both reference MudOS-only driver introspection primitives with no FluffOS equivalent; both are non-critical, non-preloaded utility/admin commands (a "show server version" command and a raw-socket-debug admin command). Left unfixed — low value, no gameplay impact./cmds/wiz/tail.lpc— the well-known §8etail()efun gap, an unused wiz command, same as lib #1's precedent. Left unfixed per that precedent.
Process notes
- Confirmed via
/proc/<pid>/cwdbefore killing anything that a secondbuild-debug/src/driver config.fluffosprocess (pid varies by run) seen in a broadpgrep/psduring this session belonged to a DIFFERENT concurrently-running agent's lib (libs/yxcs/work) — never touched it, only ever killed this lib's own driver by its exact, recorded PID. No lingering driver process for this lib at the end of this session.
2026-07-23 re-verification pass (driver rebuild + formatter + WASM)
- LPC reformat: ran
format-corpus.mjsover all ofwork/(466.lpcfiles) — 465 written, 1 already-idempotent, 0 refused. Spot- checked the §15stell_room()/message()fix inadm/simul_efun/ message.lpc(message("tell_room", str, ob, exclude || ({}));) — reformatted but semantically untouched, confirmed by reading the formatted output directly. - Native retest against the freshly-rebuilt driver: booted clean on port 40059, zero fatal preload errors. Full registration flow with a fresh real Chinese name ("秦风八"/
qinfengba) through the complete wizard (id → confirm → password → confirm → email → gender → Chinese name) into the actual game world (巫师神殿); reconnected with the same id/password and ran explicitlook(room description correct),score(full character sheet correct: stats, HP/查克拉 bars, equipment slots), andquit(clean save + disconnect) — all correct, zero runtime/compile errors logged during the whole session. No regressions from the reformat or the new driver binary. (Note for future testers: the login wizard's English id must be pure letters, 3-10 chars — digits or >10 chars are silently re-prompted, easy to burn several--sendlines on by accident.) - WASM test (
scripts/wasm_client.jsagainstbuild-wasm/src): boots cleanly (same preload warnings as native). Registration proceeds all the way through the wizard — id, password, email, gender, Chinese name are all accepted — but the character never actually lands in the game world. Root cause is a genuine WASM limitation, distinct from the documentedquery_ip_number()issue:adm/daemons/userid.lpc(an ident/authprotocol lookup against the connecting client's port 113) is lazily compiled fromlogind.lpc'senter_world()and usessocket_address()/socket_create()/socket_connect()— none of which exist under this WASM build (nosocketspackage, per AGENTS.md's documented WASM restriction list). The file fails to compile, and because this call site is a lazy runtime load at the tail end of login rather than a preloaded daemon wrapped by the mudlib's own error handler,enter_world()throws*No program in object '/adm/daemons/userid'!and aborts outright — confirmed the character was left outside any room (a same-sessionlookimmediately after returned "你现在什么也看不到" — not "in a room" at all) rather than merely a cosmetic feature gap. Confirmed via direct source read and by contrast with the fully-clean native login above (reaches 巫师神殿 every time) that this is WASM-build-specific, not a mudlib bug — not patched, since "fixing" it would mean removing a real feature (the ident lookup) to work around a driver-build limitation rather than fixing an actual bug.
WASM-enablement pass (2026-07: loopback-allow + throttle exemptions + admin seeding)
Standard pass per AGENTS.md §1.3b/e + §1.5. Gates found and patched
(loopback = 127.0.0.1/127.*/empty/non-string/malformed IP, defending
against the WASM query_ip_number() garbage-return bug):
adm/daemons/logind.lpc:80new helperis_loopback_conn()(declared :73); used to exempt loopback from:
- :120 — ENABLE_ANTISPAM per-IP registration throttle in logon()
("创造的人物太多" ≥10 registrations per IP per reset → reject);
- :180 — ENABLE_BAN_SITE banned_ip/banned_hostname pattern gate in
get_id() (both lists ship empty, but the gate is live);
- :589 — check_ip() per-account IP whitelist (okip property):
loopback always passes.
- No
uptime()startup-grace gate exists in this lib (zero non-cosmeticuptime()call sites). - Incidental fix while verifying the admin account: created
work/log/nosave/— the wizardupdatecommand's auditlog_file("nosave/UPDATE", ...)threw "Wrong permissions/No such file or directory" on every use because the archive never shipped that subdirectory (AGENTS.md §7.11 class; never seen before because no admin account existed to runupdate). Clean after mkdir.
Admin account: fluffos / Mud@2026 / 浮浮, registered through the
real native flow (id → y → password ×2 → email → gender m → Chinese
name). Granted (admin) via adm/etc/wizlist (added fluffos (admin)
alongside the original acme (admin)). Verified after restart: login
shows 目前权限﹕(admin), wizard-vision file paths visible in room
descriptions, update /world/area/wizard/guildhall recompiles the room.
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 + update clean; a stray typo character (flufos)
created during testing was deleted; one single "Too long evaluation"
eval-cost overrun was observed once in world/area/wizard NPC-inventory
creation during a first-touch lazy-compile burst (content-side, did not
recur on subsequent sessions, unrelated to this pass's patches);
data/chinese.o runtime churn reverted.
Dual-mode verification pass (2026-07-24)
- Fix applied (AGENTS.md §1.3c, in scope for this pass):
adm/daemons/logind.lpc:663(enter_world) and:713(reconnect) — the two lazyIDENT_D->query_userid(...)calls are now wrapped incatch(). Under WASMuserid.lpcfails to compile (socket_address/ socket_create/socket_connect absent — no sockets package), and the uncaught throw abortedenter_world(), leaving the fresh character outside any room (the previously-documented WASM blocker). With the catch, the ident lookup silently no-ops under WASM and is unchanged natively. Wizards see the caught compile error echoed once at login ("编译时段错误..."), cosmetic and wizard-only. - Native (temp port 41059 — this lib's assigned 40059 was held as a secondary listener by another session's xuanjianlu driver, which was left alone per §10.5;
include/globals.hMUD_PORT was temporarily pointed at 41059 for the test and reverted, byte-identical, after): fresh registrationceshier/秦风 end-to-end into 巫师神殿; re-login (restore path) + look/score/quit all correct;fluffos/Mud@2026login shows(admin)andupdate /world/area/wizard/guildhallsucceeds. debug.log: compile warnings only, zero runtime errors. Driver killed by exact PID. - WASM (build-wasm with query_ip_number/resolve fixes): fresh registration
wasmceshi/秦风 lands in 巫师神殿, look/score/quit all correct; second invocation:fluffosadmin login(admin)+update成功. Verdict: native OK + wasm OK. Test character saves removed; runtime churn (daemon.o, fluffos.o timestamps) reverted.
深度功能测试 / Deep functional test (round two, AGENTS.md §10.7)
One continuous native-driver session via scripts/mudclient.py (port
40059), test character qftester/秦风 (password Test1234,
[email protected], male).
Verified working, zero runtime errors in debug.log/driver stdout across
the whole session (only harmless pre-existing compile warnings —
unused locals, unknown #pragma): full registration wizard (id →
confirm → password ×2 → email → gender → Chinese name), MOTD pagination,
look/score/i all render correctly with no ANSI/formatting
corruption, clean quit, prompt reconnect after both a clean quit and a
simulated net-dead (raw socket abrupt-close) disconnect — both resumed
in the exact correct room with no state loss and no §7.20/§7.36-class
stranding.
Scope-limiting discovery, not a bug: include/login.h's
START_ROOM is hardcoded to /world/area/wizard/guildhall.lpc (the
wizard-staff guildhall — bug-report board, academy, propose room,
meeting room, "black magic" bug-squashing room), and world/area/
contains only the wizard/ subtree — there is no other room/zone
anywhere in this archive. Confirmed this is a property of the archive
itself, not a conversion gap: substantial NPC/weapon/food/item template
content exists under world/npc, world/eq, world/item, etc. (466
.lpc files total), but with no non-wizard rooms to place any of it in,
none of it is reachable through normal navigation. This means the
lib is playable end-to-end for what geography exists, but the round-two
checklist's combat/skill-learning/sect-join/shop steps could not be
exercised — not because of a bug, but because there is genuinely no
ordinary-player game world to test them in. Documenting honestly rather
than fabricating a test of content that isn't there.
Not verified live (only reachable via a genuinely unfinished part of
the archive, or requiring a full 900s wait not attempted this pass given
the above): a full-duration net-dead force-quit; skill learning; sect/
faction join; shop purchase; combat/death. The training-dummy object
world/npc/stake.lpc (accept_fight() unconditionally returns 1, a
real safe-sparring NPC) exists in the archive but isn't placed in any
reachable room either.
No bugs found or fixed this pass — the lib is clean for everything actually reachable. No code changes; test character save data removed after testing.
WASM 修复摘要(迁移自 meta.json 的 group_note)
Naruto 题材的 ES2/Neolith 引擎 mudlib(火影);这是正统、可游玩的原版——hy2(078,火影 (2).rar)是同一份压缩包的第二次上传,确认除排版外逐字节相同,而且它自己的 duplicate_of 已经正确指回这个 slug。这份档案自己的 duplicate_of 之前被误设成一个不存在的压缩包文件名(火影.rar),现已清除。
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 8 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
§7.114 fix: private input_line() broke multi-line to/board/mail/chfn input (2026-08-19)
Same ES2-ancestry bug as zzhj/shzs/dfgs2 (AGENTS.md §7.114):
work/feature/user/edit.lpc (this lib's F_EDIT mixin, inherited by
obj/user.lpc) declared its input_to() re-arm target private:
private void input_line(string line, string text, function callback).
The recursive re-arm from inside input_line() silently failed to
register once reached through the inherited mixin, so any multi-line
.-terminated input session (board post, to, mail, chfn) dropped
everything after the first line. Fix: dropped private.
Live-verified on a fresh driver boot (port 40059), fresh character
(秦三八/qinsanba): to say → two lines of text → . → resulting
say output showed both lines (你说道﹕test line one\ntest line two),
not truncated after line 1. Killed the driver by exact PID when done.
Files modified this pass:
libs/huoying/work/feature/user/edit.lpc— droppedprivatefrominput_line().
§7.100 sub-threshold instance (2026-08-20)
Found during the §7.100 tail-sweep (below the original 166-lib survey's
=100-occurrence threshold, never checked). 7 live
replace_program(ROOM); occurrences: 5 room files under
world/area/wizard/*.lpc (bug.lpc, propose.lpc, newbie.lpc,
guildhall.lpc, academy.lpc) plus this lib's own room-building tool
obj/roommaker.lpc's string-builder template (mixed tab/space-indent
variant, hand-fixed). A full post-fix grep confirms 0 live occurrences
remain. Verified via a clean native driver boot (zero new debug.log
errors, port listening, killed by exact PID after ~8s).
§7.126 sibling-sweep fix: stale pre-.lpc extension in AREA save data (2026-08-28)
Flagged in AGENTS.md §7.126 as a sibling worth checking (originally
found on naruto, same ES2/Neolith "Annihilator" AREA-engine
lineage). std/area/map.lpc's file_path() has the identical
macro-placeholder resolution shape as naruto's, with no strip of a
stale trailing .c left over from this project's own .c→.lpc
conversion pass. Unlike naruto (210 affected save files), this lib's
built-out AREA-grid world is much smaller — only 2 .o save files
exist under world/area/, with exactly 1 stale __DIR__...c"
reference (world/area/wizard/wizard.o). Fixed with the identical
choke-point strip in file_path() regardless of the small blast
radius, since the fix is a no-op for already-correct .lpc-suffixed
values and costs nothing to apply. Verified via a clean native driver
boot; not independently live-reproduced by walking onto the specific
affected exit tile (small enough impact that a from-scratch
reproduction wasn't warranted given the fix is a verbatim, already
live-verified port from naruto).
§10.7 deep functional test, round three (2026-09-01): actually exercising the wizard-guildhall's own content
Given round two's finding that the entire reachable game world is the
5-room wizard guildhall (bug/black-magic room, academy, propose room,
meeting room, guildhall itself — world/area/ has no other subtree),
this pass's angle was to actually USE every one of those rooms' real
commands rather than just visiting them, plus adversarial input and a
fresh look at the enable_commands()/net-dead/currency bug classes
flagged this session on unrelated lineages.
Bug board (bug.lpc room → /daemon/board/bug, the §7.86 fix):
live-verified for real this time — west to the black-magic room,
post <title> / body / . succeeded cleanly, read 1 displayed the
posted message correctly, board listing updated ([ 1 张留言 ]). Also
threw adversarial post content at it (%n%d%s in the title, %s plus
odd characters in the body) — the board's title/body fields are stored
and displayed as plain data, never passed through sprintf/printf as
part of a format string, so no crash. Zero debug.log errors.
Academy (/daemon/board/design) and propose room
(/daemon/board/propose): both are the same BULLETIN_BOARD
base class as the bug board with just a different board_id/location —
confirmed by reading daemon/board/design.lpc and propose.lpc
alongside bug.lpc (near-identical create() bodies). No separate
custom command surface beyond the inherited board verbs already
exercised above, so a second live post there would just be retesting
the identical inherited code path — not repeated.
Meeting room (meetingroom.lpc) — real bug found and fixed (new
catalog entry, see below): its own say/start/over verbs are a
genuinely custom, non-board command surface. start/over are
wizard-gated and log cleanly via a safely-parameterized sprintf. But
say's own meeting-transcript logger built its sprintf format
string by directly concatenating the raw player-typed message onto a
string literal, instead of passing the message as a %s-bound
argument. Live-reproduced as fluffos (admin) with an active meeting:
typing say hello %s world %d test while meeting_trigger was set
threw *(s)printf(): More arguments specified than passed. (arg: 1)
straight to the player's screen (caught by the driver's own top-level
command handler, so it doesn't crash the process, but it's a real,
easily-triggered runtime error visible to any non-wizard player in the
room during a meeting, not just the wizard who started it). Fixed by
splitting the format string from the data: sprintf("%s说道﹕%s\n",
this_player()->name(1), msg). Verified live: after a wizard update
of the room, the identical %s/%d-laden message now logs and speaks
normally with zero errors. New AGENTS.md §-worthy bug class: a
user-supplied string spliced directly into a sprintf/printf format
string (as opposed to passed as a %s argument) lets any embedded %
directive in player input crash the call — grep pattern
sprintf("[^"]*"\s*\+\s*<var> (a literal format-string prefix
concatenated with a variable, not passed as a trailing argument) is a
good detector. Checked the rest of this lib's sprintf call sites for
the same shape (cmds/usr/tell.lpc, cmds/usr/reply.lpc) — both
already correctly pass the user message as a %s argument, not spliced
into the format text, so they're safe; only meetingroom.lpc had the
bug.
Sibling check: naruto (same ES2/Neolith "Annihilator" lineage,
already cross-referenced for the §7.126 AREA-save fix) has the
byte-shape-identical bug in its own
world/area/wizard/meetingroom.lpc's say() — fixed there too
(sprintf("%s說道﹕%s\n", this_player()->name(1), msg)), verified with
a standalone lpcc config.fluffos /world/area/wizard/meetingroom
compile (clean, no errors) since naruto's own driver wasn't booted
this pass.
§7.19-class reentrancy check: grepped every file calling
enable_commands/enable_player for a co-located init() (the shape
that crashes a room's first-ever visit via NPC setup()/reset_me()
recursion). Only hit is feature/char/command.lpc's own
enable_player(), called from the player's own login/reconnect path,
not from any NPC's init() — no candidate NPC in this lib's tiny
reachable world has this shape. Not applicable here.
Currency/query_autoload() check (the severe fysjmb/Fengyun-
lineage §7.199 bug): std/money.lpc here already has
string query_autoload() { return query_amount() + ""; } live and
uncommented — not the Fengyun lineage, not affected.
Net-dead / tell_room() 2-arg wrapper crash (the dtsl §10.7
severity escalation): huoying was already confirmed clean for the
related heart_beat-loss-on-reconnect bug class in an earlier corpus
sweep (2026-08-19 batch 1). This pass additionally confirms the
message()/tell_room() wrapper itself is already on the safe,
guarded form (adm/simul_efun/message.lpc's
message("tell_room", str, ob, exclude || ({}));, applied as the
§15s fix at onboarding) — not re-triggered by anything exercised this
pass. Did not attempt the full 900s net-dead wait live (no new
evidence surfaced this pass suggesting this lib's user_dump() path
has the unguarded-wrapper shape that made it worth the wait on dtsl);
low remaining-risk given the wrapper fix is already in place and
independently verified.
Adversarial input: over-length email (5000 chars) correctly
rejected by the existing 64-char bound with a clean re-prompt, no
crash; a name containing a stray Latin %s inside otherwise-Chinese
text was rejected/re-prompted by check_legal_name() with no error;
board posts with %n%d%s-laden titles/bodies rendered as inert plain
text. Zero debug.log runtime errors across the whole adversarial
pass.
Files modified this pass:
libs/huoying/work/world/area/wizard/meetingroom.lpc—say()'ssprintfno longer splices the raw player message into the format string.libs/naruto/work/world/area/wizard/meetingroom.lpc— identical fix, ported (compile-verified only, not live-booted this pass).
Test character saves (advtest, hytestone) and incidental board/
admin-account save churn removed after testing; driver killed by exact
PID.
深度功能测试(§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)— 主控 author_file()/domain_file()
驱动的 mudlib_stats 包在主控载入时各调用一次 author_file(<主控文件>) 和 domain_file("/")。本库主控没有这两个 apply,所以每次启动都打印 author_file() in the master file does not work, using root_uid as fallback 和 domain_file() in the master file does not work, using bb_ui as fallback 两行,网页版每位访客的终端里都看得到。adm/obj/master.lpc 补上了这两个 apply:作者返回 get_root_uid(),域返回 get_bb_uid(),正是驱动缺少它们时所用的值。域名等于 backbone 域时,驱动让对象沿用创建者的域,与没有这个 apply 时相同(KB 06 §7.222)。两个新函数不加 nosave(本主控其余函数的 nosave 会触发 Illegal to declare nosave function 警告,属于本库尚未做的警告清理)。用 lpcc config.fluffos /nonexistent.lpc 前后对比,主控载入段只少了这两行。
深度功能测试(§10.7,2026-10-05)— 编译警告清理
1. 编译警告:启动时 约 30 条 → 0,整树扫描 215 条 → 0。scripts/lpc_warnings.py --fix:28 个 nosave 函数改 protected(被别处按名调用的 4 个去掉 nosave 保持 public)、删 CD/MudOS 专用 #pragma、删 112 个未用局部变量、29 处无效转义(BIG5 第二字节 0x5C 转码后残留的 \,如 不允許\你,KB 03)、2 处补 varargs;lpc_audit_removed_locals.py 复核 175 个被删声明,标出的 apply 是本文件的 apply() 函数调用,不是被删的变量。手工:logind 的 #if 0 分支变量移入同条件声明块,httpd 删无用的 q = query_ip_port()。
2. std/room/hockshop.lpc 的 remove() 声明为 int(父类 room 是 void),而且没有调用 ::remove(),当铺被销毁时不会像其他房间那样清理它放出去游荡的 NPC。改为 void remove() { save(); ::remove(); }。logind 的 init_new_body() 里只声明不用的 penalty 删除。
3. version 用了旧驱动的 __DRIVER__ 宏(本驱动没有,指令编译失败),改为只印 __VERSION__。cmds/adm/socket.lpc 调用 MudOS 的 dump_socket_status(),改用 socket_status(),并以 #ifdef __PACKAGE_SOCKETS__ 保护(KB 01 §1.3(c))。
4. 仍无法编译、无人引用的孤立文件(不改,属内容缺口):obj/water.lpc(F_DRINK、feature/drink 不在本档案)、world/item/mj.lpc(ansi2.h)、world/item/gobang.lpc(path.h),都是从别的库带进来的。
5. 验证:§9 格式化(4 个文件只调整 :: 前的空格)后全新启动 0 警告;fluffos 登录 → who、version、tell、reply、socket、score、quit 全部正常。
深度功能测试(§10.7,2026-10-08)— .lpc 后缀的定宽切片
.c 改名 .lpc 时只改了字符串没改切片宽度:f[<2..] == ".lpc" 拿两个字符比四个字符,永远不成立(!= 永远成立),按后缀筛文件、去后缀的代码因此从不运行或截成 x.l(KB 06 §7.238)。scripts/lpc_lpc_suffix_slice.py --apply 改了 1 处比较、0 处去后缀(如 cmds/wiz/update.lpc);改动的文件 HEAD 与工作树分别加载(新进程),无回退。
- 2026-10-14:新驱动(FluffOS 970d9f09)报
Float value truncated to int(#1426)。1 个文件 1 处:赋值、初始化、return 改写成to_int(...)(值不变,只是写明截断)。改动的对象新进程各载入一次,无回退(scripts/lpc_fix_float_trunc.py,KB 04 §6.10)。
表情档读不出来(2026-10-15,KB 03 §4.4)
data/emoted.o 的结尾是 ]),],少了最后一个 )(raw/ 原档就是这样),restore_object() 报 Illegal mapping format,表情系统一个表情都没有。补上括号,驱动核对能读回。
存档读不出来:字符串里的换行、空行(2026-10-15,KB 03 §4.4)
data/questd.o、world/area/wizard/hockshop.o:字符串里有原样的换行(save_object() 存成 \r,restore_object() 逐行读,原样的换行让字符串收不了尾),或有空行(Illegal file format),读档的对象(留言板、NPC、玩家)从空白开始。换行改写成 \r、删去空行(scripts/lpc_save_encoding.py --from-raw),驱动核对全部能读回(scripts/lpc_save_restore_check.py)。
move() no longer raises on a destination file that does not exist (2026-10-18, KB 06 7.96)
move() of feature/move.lpc used err = catch(dest = load_object(dest)) as an existence test, but load_object() of a missing file returns 0 and the catch never fires; dest->receive_object() then raised Bad argument 1 to EFUN call_other(). A bulletin board whose location is a wizard's room the archive lacks died in std/bboard.lpc setup() and took the room that creates it along. if (!objectp(dest)) return 0; after the catch: the move fails and the object stays where it is. The sampled boards already loaded, so this is a safeguard.
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,共 3 处)。改动:/world/item/mj.lpc(3 处)。
登录密码超过 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/user/more.lpc。
存档里的 .c 文件名改成 .lpc(2026-10-21,KB 03 §4.2 第 9 项)
存档里写着 "/d/city/npc/wei.c" 这样的文件名;extract 时源文件已经全部改成 .lpc,而驱动对带扩展名的路径只认字面,new() / load_object() / move() 都找不到它,调用方多半把失败当成「没有这个东西」悄悄跳过。本库 1 个存档共 1 处按 scripts/lpc_fix_save_dotc.py 改成 .lpc(只改 .lpc 存在而 .c 不存在的字符串;玩家存档、备份、留言板、巫师目录和文件索引缓存不动)。改动:/world/area/wizard/hockshop.o(1 处)(共 1 个存档)。
chpass:先把参数写进日志,再对它 sscanf(2026-10-21,KB 06 §7.336)
管理员扫描里 chpass 不带参数报 Bad argument 1 to sscanf() Expected: string Got: 0.(cmds/adm/chpass.lpc):指令先 log_file("nosave/CHPASS", ... arg)(%s 吃得下 0),再 sscanf(arg, "%s %s", userid, new_passwd)。静态扫描只看第一次提到参数的语句,现在会越过这种只是打印或记录的提及;在记录之前加 if (!arg) return notify_fail("指令格式:chpass <使用者代号> <密码>\n");。
log/ 下的日志子目录没有人建:写日志的 write_file() / log_file() 报错(2026-10-22,KB 06 §7.358)
这个库的代码往 log/ 的 2 个子目录写日志:log/http(obj/http.lpc)、log/intermud(adm/intermud/i2d.lpc)。压缩包、git clone 和站点包里都没有这些目录(本地启动没有写过它们,gen_keep_dirs.py 没记),write_file() 对不存在的目录抛 *Wrong permissions for opening file /log/dlog/money for append. "No such file or directory",调用它的函数在写日志那一行中断,后面的奖励、标志、步骤都没有执行。本库的 log_file() 是 write_file(LOG_DIR + file, text),目录不存在就抛同样的错误(实测)。把 log/http、log/intermud 记进 scripts/wasm_keep_dirs.txt(scripts/lpc_keep_log_dirs.py;站点和 pristine 树按它建空目录)。证明(scripts/lpcc_eval.py,在 /adm/daemons 这类目录下的求值对象里写 /log/zzdirprobe/...,新进程)见 KB 06 §7.358 的实测表。
按字节写的汉字循环、茶馆猜诗和同盟频道标题(2026-10-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-27,§6.10 未知 pragma save_binary/optimize)
删除本库中 FluffOS 不认的 #pragma save_binary / #pragma optimize… 行。