Twin Dragons of the Tang Dynasty

✅ 可玩

大唐双龙传 (Twin Dragons of the Tang Dynasty)

dtsl

🔑 fluffos / Mud@2026 更新 740c838 2026-09-01 源码 下载 ZIP

▶ 开始游玩 · Play Now

取材自黄易同名武侠小说,以隋末唐初风云变幻的江湖为背景。本站收录的 dtsl、dtsl2、dtslmud 三份档案实为同一套"大唐双龙"世界观内容——逐档比对发现三者的地图与剧情文件(58 个分区、约 5,100 个文件,涵盖石龙武馆、净念禅院、阴癸派、突厥、东溟派、慈航静斋、海沙帮、高丽等)99%以上字节级一致,真正的差异在于各自独立的服务器与安全层实现(登录流程、密码规则等),而非各自独立创作的剧情。新角色从"大唐学院"起步,下山(`down`)即进入石龙武馆——新手枢纽区,提供银行存取、`qiecuo` 安全切磋、NPC 教学式学艺(`xue`),以及经由各门派入口 `bai` 拜师入门的完整新手引导。

English

Based on Huang Yi's wuxia novel of the same name, set in the jianghu as the Sui dynasty collapses and Tang rises. This collection holds three separate uploads of what turns out to be essentially the SAME authored game world: a file-level check found dtsl's own domain tree (58 zones, ~5,100 files -- including 石龙武馆/Stone Dragon Martial Hall, 净念禅院, 阴癸派, 突厥, 东溟派, 慈航静斋, 海沙帮, 高丽, and dozens more) is 99%+ byte-identical to sibling dtsl2's and ~99% identical to dtslmud's -- the three archives are different server/security-layer implementations (distinct master.c/logind.c, registration flows, password rules) wrapped around nearly the same content, not three independently-written storylines as earlier framed. New characters begin at the Great Tang Academy and descend (`down`) into 石龙武馆, the newbie hub offering banking, a room-scoped `qiecuo` safe-sparring verb, organic NPC-taught skills (`xue`), and `bai`/`apprentice` sect-joining through the hub's own sect-gate exits. This archive's own passwords are 5-8 characters with no complexity requirement (siblings enforce stricter rules).

README

内容亮点

在线试玩

https://mudlibs.fluffos.info/dtsl/

管理员账号 / Admin account

警告:Mud@2026 是本地游玩用的公开默认密码。若要正式对外开放主机,
请先修改此密码。

本地运行

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

游戏端口:40008

NOTES · 移植与修复记录

dtsl.rar → dtsl

Status: DONE — boots clean, playable over telnet

Booted with zero fixes needed on the first attempt (matching lineage to lib #1, and lib #1's proactive checks — no load_object in valid_read/valid_write, get_root_uid() present — all held here too).

What was fixed (all from the lpcc sweep, not the boot path)

1. Encoding: 6870 converted, 327 already UTF-8/ASCII, 377 skipped binary, 4 lossy. .c.lpc: 6521 files, 1037 refs auto-fixed. staticnosave: 87 files. 2. F_UNIQUE macro was referenced (inherit F_UNIQUE;) by ~91 clone item files but never #defined in include/globals.h, despite feature/unique.lpc (the file it should point to) existing — added #define F_UNIQUE "/feature/unique.lpc" alongside the other F_* macros. Fixed all ~91 files' "unexpected L_IDENTIFIER" errors in one shot (misleadingly, the error pointed at the NEXT line's inherit F_UNIQUE, since the undefined macro parses as a bare identifier where a string/path was expected). 3. 6 clone/weapon/*.lpc legendary-weapon files (jin-sjian, shizi, feihuangshi, jinhua, sjian, feidao) redundantly inherit COMBINED_ITEM; directly AND via inherit THROWING; (which already inherits COMBINED_ITEM itself) — a diamond that this driver's stricter nomask conflict detection rejects (Illegal to redefine 'nomask' function '_query'/'_delete'/'_set'/'weight'), where an older/ more permissive driver apparently just deduplicated it silently. Fixed by deleting the redundant top-level inherit COMBINED_ITEM; line (kept the one reached transitively via THROWING). Gotcha while fixing: these files use CRLF line endings — a sed '/^inherit X;$/d' silently no-ops on a line ending ;\r\n because $ doesn't absorb the \r; needed /^inherit X;\r?$/d. 4. clone/weapon/sm_ding.lpc (7th file in the same cluster) has a DIFFERENT, unrelated problem: #include "/inherit/item/embed.h", which doesn't exist anywhere in this archive — genuine missing content, not fixed (not fabricating a header).

Known remaining issues (documented, not fixed)

How to run

cd libs/dtsl
~/src/fluffos/build-debug/src/driver config.fluffos
python3 ../../scripts/mudclient.py 127.0.0.1 40008 --timeout 10 --send "" --send "look" --send "quit"

Retroactive fix (QA re-verification pass, 2026-07-23): log_error() compile-warning spam (AGENTS.md §15af)

Found during a routine re-verification pass (full registration + post-login look/score/quit test): adm/obj/master.lpc's log_error() showed the config's scary default error message ("你发现事情不大对了,但是又说不上 来。") to the connected (non-wizard) player for every compile-time diagnostic funneled through APPLY_LOG_ERROR — including harmless "Unused local variable" warnings triggered by the first lazy compile of an ordinary room/NPC the player merely walked into (e.g. /d/job/...'s job_money.h-included files, /cmds/std/look.lpc, etc). In a real registration+play session this fired dozens of times per minute of walking around — same bug class already documented and fixed on wuhanzhan/ shenzhou (§15af). Fixed identically: only show the default-error message when message does NOT contain the substring "warning:" (still logs every diagnostic to the per-file log either way; only the in-band player-visible alarm is gated). Re-verified with a fresh registration (real name 秦北) followed by look/score/quit — zero spam, zero real error: lines in debug.log.

Post-hoc fix: UTF8-native is_chinese/registration (AGENTS.md §15h)

Applied in a later batch pass across the whole project: is_chinese/is_chinese2 in the shared chinese.lpc simul_efun fragment used GBK byte-range checks that silently never match real Chinese text once strings are UTF-8 (this driver's str[i] returns a Unicode codepoint, not a GBK byte). This broke character registration specifically -- any real Chinese name was rejected. Fixed the range check to test the CJK Unicode block instead, and halved the GBK-byte-calibrated length bounds in check_legal_name to match. See AGENTS.md §15h for the full writeup; confirmed via a real interactive registration test (Chinese surname + given name reaching the next prompt).

Re-verification pass (2026-07-23): driver rebuild + LPC formatter + WASM build

WASM-enablement pass (2026-07 standard: loopback-allow, admin seed)

Same "大唐双龙" simple-lineage shape as sibling dtsl2 (byte-identical adm/daemons/band.lpc/sited.lpc) -- checked directly rather than assumed:

Admin account: id fluffos / Mud@2026 / 浮浮, registered through the normal flow (id -> confirm y -> Chinese name 浮浮 -> password x2 -> email skipped -> gender m -> stat allocation 20 20 20 20 -> confirm yes), granted (admin) via adm/etc/wizlist (fluffos (admin) line added, existing fengfei/kouzhong/ttj/zhujiepo entries kept) before registration, so wizard status was active immediately ("作为巫师,你可以迅速离线" shown on the very first quit). Verified on a SEPARATE re-login: password accepted, update /d/newbie/door succeeded ("重新编译 /d/newbie/door.lpc:成功!") -- unlike sibling dfgs2, this lineage's restore path has no permission bug, re-login just works. Save files (data/user/f/fluffos.o, data/login/f/fluffos.o) are plain untracked paths, not covered by any .gitignore pattern -- a normal git add libs/dtsl/ picks them up, no force-add needed.

Retest: fresh normal registration (id ceshijiu, name 秦鹏, female) reached 大唐学院, look correct, clean quit. debug.log clean across both driver runs this pass (only expected boot-time config dump and SIGTERM-on-kill lines -- the visible "编译时段错误" warning spam during fluffos's OWN session is expected/correct: this lib's log_error() fix (see above, 2026-07-23 pass) shows full diagnostics to wizards and only gates the generic scary message for non-wizards, and fluffos is a wizard). Two driver instances started/killed by exact PID; test character ceshijiu's saves removed afterward (data/user/c/ ceshijiu.o, data/login/c/ceshijiu.o), fluffos's kept. Note: this lib's data/user/+data/login/ trees already contained other untracked leftover test saves (e.g. q/ shard, from this lib's own earlier qinnuo/qinao verification passes documented above) predating this session -- left untouched as out of this pass's scope.

深度功能测试 / Deep functional test (2026-07-24, round two)

First real *playthrough* pass on this lib (all prior passes verified only registration + look/score/quit + admin login, or watched boot output). Read doc/help/newbie in full first -- it named the fight-vs-kill distinction, the bai/skills(cha)/xue teaching loop, and dazuo/tuna cultivation up front, matching the methodology's prediction that it's the fastest way to learn the intended path. Played as an ordinary new player through registration, exploration of the d/slwg (石龙武馆) newbie hall, the lib's own room-scoped qiecuo safe- sparring command, the organic paid-teacher xue path (both a failing and a successful attempt), the bai/apprentice sect-join mechanism, a real sleep/wake cultivation cycle, a real quit, a real prompt net-dead reconnect, and a real 15-minute (NET_DEAD_TIMEOUT) unclean- disconnect wait to force the force-quit path, all on the native driver (build-debug). Found and fixed two bugs, both new classes for this project's catalog: a command-dispatch duplication bug (Bug 2, found first) and, from the mandatory real 15-minute wait, a critical tell_room() type-error bug (Bug 1) that disables the net-dead force- quit safety net entirely and was observed to crash the whole native driver process outright -- see Bug 1 below for the full story; it is by a wide margin the more important finding of this pass.

Test character (kept, not cleaned up, as representative playthrough evidence): id qintian, Chinese name 秦天 (male), password Qt12345. State: received the newbie 礼官 gift (combat_exp 6000, +1 to all four attributes), sparred a 弟子 via qiecuo at 石龙武馆's 练武场, withdrew and spent savings on a (gated-out, already-capped) xue jiao force lesson, survived a full quit→save→relogin round trip with all of the above state intact, and was the character used to reproduce and then re-verify the bug below across a prompt net-dead reconnect, a sleep/ wake cycle, and the full 15-minute net-dead force-quit path. Saves: work/data/user/q/qintian.o, work/data/login/q/qintian.o (state as of the pre-Bug-1-investigation clean quit, since the later crash meant no further save occurred for this id). Secondary throwaway characters created to isolate Bug 2 (ceyanzc/测验者, shuimian/沉睡) and to reproduce/verify Bug 1 (ceyanzc again, plus wangce/网测 and zongjian/总检, and goumai/购买者 for the shop-purchase check, all password Ab12345) were left in place rather than risk clobbering evidence mid-investigation -- their saves are harmless, ordinary fresh-registration state.

Bug 1 (CRITICAL, NEW bug class): a 2-argument tell_room() call inside user_dump()'s net-dead force-quit path crashes with an uncaught runtime error, permanently disabling the 15-minute net-dead force-quit safety net -- and, worse, appears to be the trigger for an actual DRIVER-LEVEL CRASH (full outage) observed live

File:line of the fix: adm/simul_efun/message.lpc's tell_room() (line 47-54). Directly reached from obj/user.lpc's user_dump() (line 182-183), the NET_DEAD_TIMEOUT-driven call_out handler that force-quits a player who never reconnects.

`` 执行时段错误:*Bad argument 4 to EFUN message() Expected: object, array, Got: int(0). 程序:/adm/obj/simul_efun.lpc 第 49 行 呼叫来自:/obj/user.lpc 的 user_dump() 第 182 行 ... 调用参数:tell_room("秦天断线超过 15 分钟,自动退出这个世界。\n", NULL) ` A few driver ticks later, reconnecting as either character crashed the entire native driver process with a fatal C-level abort (not an LPC-catchable error) -- md: debugmalloc: attempted to free non-malloc'd pointer ... inside dealloc_object()/free_svalue(), triggered while indexing a mapping whose value was a destructed object reference (assign_svalue()'s destructed-object auto-null path at interpret.cc:3792`), captured in the driver's own crash backtrace (printed to the driver's redirected stdout at the time -- not preserved as a repo artifact, this is a description of what was observed live, not a file left behind). This took the whole MUD down for every connected player, not just the two net-dead characters -- categorically the most severe finding of this pass, and of this project's round-two testing effort to date.

``lpc // BEFORE: message("tell_room", str, ob, exclude); // AFTER: if (exclude) message("tell_room", str, ob, exclude); else message("tell_room", str, ob); ` This is the single, root-cause fix point for the whole shared-root- cause bug -- it doesn't require touching any of the 80+ individual call sites, since the type violation only ever happens inside tell_room()`'s own forwarding call.

Bug 2 (NEW bug class): every enable_player() call beyond the first silently stacks a duplicate command-dispatch sentence, so any FAILING command runs its side effects more than once

File:line of the fix: feature/command.lpc's enable_player() (~line 79-105). Root cause is distributed across several call sites, none of which look buggy in isolation: adm/daemons/logind.lpc's enter_world() (~line 554, a direct user->enable_player() call, immediately followed a few lines later by user->setup(), which itself calls enable_player() again via std/char.lpc:50) and cmds/std/sleep.lpc's wakeup() (lines 43/61/67, three unconditional calls in a row on every single sleep-and-wake cycle).

`` 你现在的学费是每次三文铜板,请备好零钱。 你现在的学费是每次三文铜板,请备好零钱。 武馆教头说道:您太客气了,这怎么敢当? ` Nothing in debug.log — no error, no warning, zero log signal, the single hardest-to-notice shape in this catalog (matches the framing of §7.20's "zero signal in debug.log" but via a completely different mechanism). A player would have to be looking closely at the *exact* wording of a rejection message to ever notice; a resource-costing success path (a rejection with a side effect already applied before the failure return, exactly learn.lpc`'s shape here) would silently cost twice what it should, with no error to grep for afterward.

- qintian, immediately after a fresh login: a single failing xue jiao force now prints the tuition message exactly once. - ceyanzc/测验者, fresh registration → xue jiao force (fails, single message) → withdrew savings → xue jiao force again (succeeds, tuition charged exactly once, correctly then gated by the *separate*, correct "已经无法再进步" skill-cap check, not a regression) → full sleep/25s-real-wait/wake cycle → look/ score/xue jiao force all immediately functional afterward (the regression's exact repro scenario), single dispatch confirmed throughout. - shuimian/沉睡, an independent control character, used specifically to catch the living()-guard regression (which it did) and then to confirm the remove_action() fix resolved it (which it did). debug.log clean (no error:/Too deep recursion/Undefined function) across every iteration of this investigation.

What was tested and confirmed working

Not verified live (explicitly flagged, not silently skipped)

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

此前被错误标记为某个不存在于本项目任何档案的原始压缩包文件名(dtsl.rar)的 duplicate_of——那份"兄弟"上传显然从未被真正转档过,所以这份 7z 重新打包版是这款游戏唯一存活、完全独立的副本。duplicate_of 已清除。

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

Deep functional test round two (2026-08-14)

Independently re-verified against current code rather than trusting the round-one writeup above. This is by a wide margin the highest-stakes lib on this session's re-test list — round one's Bug 1 was a driver-crash- class finding — so the priority this pass was re-confirming it live, at real (accelerated) accuracy, not just checking the diff.

Re-verified live at accelerated timing: Bug 1's tell_room() fix (the driver-crash-class §7.12 finding) still holds

Confirmed the if (exclude) message(...); else message(...); fix is still present in adm/simul_efun/message.lpc, then re-ran the same accelerated methodology round one used: temporarily changed include/user.h's NET_DEAD_TIMEOUT from 900 to 20 (restored to 900 immediately after, confirmed via git diff returning empty), rebooted, logged in as fluffos, raw-killed the tmux session running its telnet connection (genuine socket drop, not quit) to trigger a real net-dead, waited a real 26 seconds past the shortened timeout. Result: work/log/debug.log's line count was unchanged before/after (no Bad argument 4 to EFUN message(), no anything), the driver process stayed alive (ps-confirmed by exact PID), and reconnecting as fluffos landed in a genuinely fresh enter_world() — confirmed by the "上次连线" (last-connect) banner showing the *previous* login's timestamp rather than a stale in-memory resume, proving user_dump()'s save()+destruct() path actually ran to completion this time. Did not re-attempt the two-simultaneous-character double-free reproduction from round one (a one-time, already-rigorously- documented confirmation of a downstream C-level consequence of the same root cause) — re-triggering the LPC-level root cause and confirming it no longer throws is sufficient to confirm this specific fix still holds.

Re-verified: Bug 2's enable_player() duplicate-dispatch fix still holds

Code-confirmed the remove_action("command_hook", "")-before-add_action() guard is still present in feature/command.lpc, with its explanatory comment intact.

New fix, and a near-miss: adm/simul_efun/file.lpc's log_file()/cat() hardening

Standard §7.11-class gap: cat() had no null-guard, log_file() had no assure_file() guard. First attempt at this fix defined log_file() (which calls assure_file()) BEFORE assure_file()'s own definition with no forward declaration — this driver does NOT tolerate forward references within a single file the way some LPC drivers do, and it broke the ENTIRE boot (Error: Undefined function assure_file inside /adm/simul_efun/file.lpc, cascading to No program in object '/adm/obj/simul_efun'! — nothing loads, not just this one function). Caught immediately by checking the boot log rather than assuming success; fixed by adding a void assure_file(string file); forward declaration before log_file(), matching the pattern already used correctly on this session's other libs (bxsj/dfgs2/dfgsiiv13b) — this lib's file.lpc just happened to have log_file() textually before assure_file() in the source, which those others didn't.

Checked and confirmed already correct, no action needed: log_error()'s severity gate already uses the case-agnostic strsrch(message, "arning:") check; no §8.9 food/water wrong-object read; the one printf("%O\n", ob) in logind.lpc is already commented out (dead code, harmless).

Observed, not investigated: an unrelated wizard-channel message during idle time

【系统】系统核心:/std/char/npc.lpc 第 11 行,物件:/d/gaoli/npc/xiake *Read access denied. appeared once, unprompted, during an idle stretch between commands (some background/heartbeat-driven NPC action hitting an ACL check). Not connected to either fix above, not a crash, no player- facing impact observed — flagged for whoever does a full playthrough pass on this lib next, not chased further this pass since it's outside this pass's scope (re-verifying round one's fixes plus the standard checklist).

Verification method

Booted native build-debug driver, admin login (fluffos/Mud@2026), update /adm/daemons/logind as the real privileged-action check (succeeded). Two rapid consecutive admin reconnects, both clean. Driver killed by exact PID after each reboot (three total this pass: initial boot, accelerated-timeout boot, final clean-config boot); incidental fluffos.o save-timestamp churn reverted before commit.

Files modified this pass

Round three deep functional test (2026-08-18)

Went past round one/two's scope on purpose: this pass targeted the items round one/two explicitly left "not verified live" (a full sect-join round trip, a successful funded shop purchase, real combat death/respawn) plus systems neither prior round touched at all (bulletin boards). Also confirmed the adm/obj/master.lpc §7.111 standard_trace() fix from today's corpus sweep wasn't disturbed (not independently re-exercised, since nothing in this pass triggered a driver-level error until the bug investigation below, whose repro's own driver-level-adjacent trace stayed clean throughout — see Bug 3).

Method: booted native build-debug driver; ran two-connection live sessions (admin fluffos + fresh test characters) via a raw Python socket harness (hard wall-clock recv budgets per AGENTS.md §10.7, no reliance on quiet-detection). Used goto/summon/force/clone/ give (all real cmds/imm|wiz|adm commands) to reach content round one/two's time budget didn't stretch to.

Confirmed working, no bug: full sect-join round trip

Test character shenceng/深层 (male, fresh registration) was summoned to 净念禅院's d/chanyuan/wuchang (虚尘's room) and forced to run apprentice xu chen. Full chain fired correctly end-to-end: cmds/std/apprentice.lpcmain()xuchen.lpc's attempt_apprentice() (gender/family/couple/PKS/bellicosity gates, all satisfiable by a fresh male character) → command("recruit " + id)cmds/std/recruit.lpcfeature/apprentice.lpc's recruit_apprentice()/assign_apprentice(). score afterward correctly showed title 【俗家弟子】, 称谓 "净念禅院第 八代弟子", 师傅 "净念禅院 虚尘". This closes round one's "not verified live" item — no bug in this chain.

Confirmed working, no bug: economy (funded purchase)

Used a genuine two-connection live session (admin + shenceng, both connected simultaneously) rather than force for this one, since cmds/std/give.lpc's do_give() gates on interactive(who) (an offline/netdead recipient falls through to an NPC-only accept_object() call_other, which silently no-ops for a player target — confirmed this is why an earlier force-based give gold to shenceng attempt failed with "对方不要你的东西" while shenceng was disconnected; not a bug, give to an offline character is a reasonable design gate, not chased further). With shenceng actually connected: admin cloned /obj/money/gold and give-gave it, then shenceng ran buy sword from tiejiang (d/slwg/bingqipu) — correct purchase, correct automatic denomination change (2两黄金 → 长剑 + 99两银子), 讨价还价 skill ticked up. Closes round one's "not verified live" item — no bug.

Confirmed pre-existing, not new: the round-two-flagged xiake "Read access denied"

Round two observed, but didn't investigate, an unprompted *Read access denied. on /std/char/npc.lpc:11 for object /d/gaoli/npc/xiake. Traced this pass: adm/daemons/jobmond.lpc's do_start_job() (its own periodic job-posting/NPC-restocking heartbeat, independent of any player action) tries to move() a job NPC into one of a hardcoded room list including /d/gaoli/qinglong-1, and xiake.lpc's create()carry_object()s a weapon/armor via new() under an ACL context that gets denied. Confirmed this is the exact same jobmond.lpc room-list content gap already documented for sibling dtsl2 (not this lib's own new finding) — fires from jobmond's own independent heartbeat during ordinary boot/idle time, unrelated to any of this pass's live test paths. Left unfixed, as already established for the sibling.

Bug 3 (NEW bug class, FIXED): reconnecting while a character sits in the death/ghost sequence stacks a duplicate death_stage() call_out chain, misdirecting the revival room and risking a double-applied death penalty

File:line of the fix: d/death/npc/yanluo.lpc's init() (~line 51) and death_stage() (~lines 61, 78).

- Interleaved/duplicate narration is the visible-but-harmless symptom. - The real damage: EACH chain independently runs the terminal branch (item-drop loop, lose() PK/combat_exp penalty, and the zuolao/combat_exp/zoulang1 room-move decision) when it reaches its own final stage. Whichever chain finishes LAST calls ob->reincarnate() a second time, which the earlier-finishing chain(s) already did — meaning by the time a stale second chain checks !ob->is_ghost() at the top of death_stage() (a check meant to catch a non-ghost object wandering in by mistake), ghost has *already* been reset to 0 by the first chain's completion, so the stale chain takes the "you're not actually a ghost, teleporting you to REVIVE_ROOM" shortcut (lines 61-70) unconditionally, silently overriding whatever room the real chain's combat_exp/zuolao branch had already (correctly) chosen. A character with nonzero combat_exp reconnecting mid-sequence could additionally have lose()'s PK/exp penalty applied more than once.

Confirmed working, no bug: bulletin board post/read/list

Tested at 净念禅院's obj/board/party_cy_b.lpc (placed in d/chanyuan/miaodoor via its own setup()'s move(query("location")) — the room's "...party_cy_b.lpc"->foo() call is a harmless no-op, foo() is undefined anywhere in the inheritance chain, same silent-0 call_other idiom as attempt_apprentice() on a non-recruiter NPC, already documented in round one; it's there only to force the singleton board to compile-load once at room-create() time). list correctly showed a pre-existing real player note; post <标题> (4 Chinese chars, even length, per do_post()'s gate) correctly invoked the line editor (me->edit(...), . to end); the new post was correctly appended and read 2 rendered it back with correct author/time/title/body formatting. No bug.

Verification method / cleanup

Two native driver boots this pass (initial, then post-fix). Both killed by exact PID after readlink /proc/<pid>/cwd confirmed this lib's work directory. Incidental data/user/f/fluffos.o + data/login/f/fluffos.o (admin account) and data/orgroom/baling.o (unrelated background-daemon resave, pure key-reorder no value change) save churn reverted before commit via git checkout -- on those specific files only. Kept as evidence: shenceng/深层 and chongshi/重试 test character saves (both data/user/ and data/login/), and the real board-post content change in data/board/party_cy_b.o + data/board/all_post_b.o (the aggregate board mirror, which legitimately picked up the same new post). work/log/debug.log never existed at any point this pass (no runtime errors triggered outside the Bug 3 investigation itself, which is LPC-catchable and doesn't write to debug.log when caught cleanly by the top-level dispatcher). Two harmless "Too deep recursion" lines appeared once in boot.log during the very first cold boot's daemon- preload sequence (adm/simul_efun/file.lpc:32 / adm/obj/master.lpc:396log_file()assure_file()mkdir()valid_write()SECURITY_D mutual bootstrap ordering during the earliest part of preload, before SECURITY_D itself is fully loaded), self-resolved (Initializations complete. still printed, never recurred during ~40 minutes of live testing afterward) — flagged here, not investigated further, since it's boot-time-only and unrelated to every live path this pass exercised.

Round four re-test (2026-08-19): full catalog checklist, clean — no new bugs

Re-checked this lib against the current AGENTS.md catalog items that didn't exist (or weren't corpus-swept) when round one/two/three ran, plus a fresh full §10.7 playthrough with a brand-new test character. All items came back clean; no code changes this pass.

Fresh §10.7 playthrough (test character huice/秦回, male, password

Hc123456)

work/log/debug.log never existed at any point this pass (no runtime errors triggered by anything tested) — the only anomaly in the boot log was the same pre-existing, already-documented jobmond.lpc/xiake *Read access denied. content gap from round two/three's own independent heartbeat, confirmed byte-identical, not a regression.

Cleanup

One native driver boot this pass, killed by exact PID after confirming readlink /proc/<pid>/cwd matched this lib's work directory. Incidental data/login/f/fluffos.o + data/user/f/fluffos.o (admin save-timestamp churn) reverted via git checkout -- before commit. Kept as evidence: huice's saves (data/user/h/huice.o, data/login/h/huice.o) and the real board-post content change (data/board/party_cy_b.o + data/board/all_post_b.o).

§7.100 扫描修复(ROOM 基类多余 replace_program()

#define ROOM "/std/room":删除 686 处多余的、独立成行的 replace_program(ROOM);(保留 inherit ROOM;),与手足档案 dtsl2 同一血统同一形状(obj/roommaker.lpc 字节级一致)。其中 685 处由脚本自动删除,另 1 处在 obj/roommaker.lpc 第 138 行—— "克隆我所在的房间"命令的字符串拼接模板把同一枚多余调用烤进了每一 个新克隆的房间,已同步手动修正(删除该片段,保留 str += "\n\tsetup();\n}\n";)。修复后全库仅剩 82 处历史遗留的 //-注释掉实例,均确认无害、未改动。已用 build-debug 驱动干净 启动验证(0 个新增编译错误,端口 40008 正常监听,debug.log 无 新增 "cannot replace"/"cannot bind" 行);未做完整 §10.7 深度 游玩测试。

深度功能测试(round three, 2026-09-01)— clean, no new bug found

A genuinely different-angle pass, per the standing rule that "already tested" libs keep turning up new bugs when probed differently. Booted native build-debug (port 40008), used a raw Python socket harness (recv_for(seconds) fixed-wall-clock reads, no quiet-detection) rather than tmux_mud.sh. Five angles targeted, all came back clean:

1. Mail system: does not exist in this lib. The only mail-named files (adm/daemons/sendmaild.lpc, adm/daemons/network/mail_serv.lpc, netmail.lpc, include/net/sendmail.h) are real internet-SMTP daemon plumbing (the sockets-package-gated networking subsystem, already documented elsewhere as WASM-incompatible but otherwise inert), not a player-to-player in-game mail command. Confirmed via grep across cmds/ for any add_action on "mail" — none. N/A, not a gap in testing coverage. 2. Board post/reply: this lineage's boards (std/bboard.lpc / obj/board/*.lpc) have no reply verb at all — only post/read/list/discard (confirmed via long()'s own usage text). post/read/list were already live-tested in round three; this pass added adversarial discard/read/list arguments (discard 999/-1/0/abc, read -5/abc, list -1/a 20-digit-overflow number) against 洛阳d/luoyang/zhulou's 花间弟子留言板 (/obj/board/party_hj_b) — every out-of-range or non-numeric case returned a clean notify_fail()/format-hint message, zero debug.log output. Also re-confirmed the §7.86 BULLETIN_BOARD-replace_program() corpus-sweep fix has no remaining instances (grep -rn "replace_program" | grep -i board returns nothing). One incidental finding, NOT a bug: a wizard-only post (bypassing the non-wizard 2-24-char/Chinese-only title gate, per do_post()'s own if (!wizardp(me)) {...} else if (i > 24) branch) left mid-edit() when the test connection net-deaded before the closing . — the pending post was correctly discarded on reconnect (no partial/corrupted post appeared), consistent with the already-documented §10.10 "an in-progress input_to()/edit chain doesn't survive reconnect" driver behavior, not a new defect. 3. Currency persistence across quit/reconnect (the exact angle that found fysjmb's severe dead-query_autoload() bug this session): checked std/money.lpc directly first — string query_autoload() { return query_amount() + ""; } (line 7) is already live, not commented out, unlike the Fengyun-lineage sibling family. This lineage is unaffected by that bug class. Live-verified anyway: test character ceshiq/测钱 withdrew 5 coins from 石龙武馆's 账房 (withdraw 5 coin), confirmed carrying 五文钱(Coin) via i, did a real quit (clean, no debug.log output), waited a real 12s, and reconnected — i and score's 存款/inventory both showed the exact same 5-coin cash and 10-coin deposit intact. No bug. 4. Adversarial/malformed input: a 10,000-character English "id" during registration, control-byte/ANSI-escape-embedded strings ("abc\x00\x01\x1b[31mdef\x07"), raw invalid-UTF-8 byte sequences (\xff\xfe\x80\x81, an encoded UTF-16-surrogate pair) and a 3,000-character valid-Chinese-codepoint string all fed into the id and Chinese-name registration prompts — every case was cleanly rejected by check_legal_id()/check_legal_name()'s existing length/charset gates (the NUL-containing string was silently truncated to its prefix, "abc", by the driver's own C-string handling before LPC ever saw it — a known telnet/socket-layer behavior, not an LPC bug) with zero debug.log output in any case. Mid-game: bai <nonexistent-npc-name>, xue <teacher> <nonexistent- skill-name>, buy with no args, a 5000-character item name, buy sword from <nonexistent-vendor>, and sell sword (no vendor context) all produced normal in-character "什么?"/"你要跟谁买东 西?"-style rejections, never a crash or debug.log entry. 5. §7.19-class reentrancy via enable_commands()/enable_player() reachable from an NPC's init(): grepped every enable_commands() call site in the lib. Only feature/command.lpc (the dispatcher itself), obj/user.lpc, d/death/npc/yanluo.lpc (round three's already-fixed §7.112 death-stage bug — re-confirmed the in_death_stage guard is still present at lines 73/74/83/101), and u/fengfei/object.lpc (a personal player-directory WIP file, already documented elsewhere as non-playable/out-of-scope content, not part of any real game path) call it. Every enable_player() call site funnels back through feature/command.lpc's own enable_player() (confirmed the round-two §7.16(Bug 2) remove_action("command_hook", "")-before-add_action() guard is still present, lines 108-109) — this defends against duplicate-dispatch regardless of how many unrelated call sites (feature/move.lpc's living-toggle logic included) redundantly invoke it. Live-reconfirmed with a real failing xue jiao force against ceshiq (single "缺乏实战经验" message, not doubled) that this fix has not regressed since round two.

Net result: no new bug found. This is an honest clean pass, not a forced one — work/log/debug.log never came into existence at any point across roughly a dozen driver interactions (registration, combat, economy, board edge cases, adversarial input, quit/reconnect), and the driver's own captured stdout showed only expected preload compile-warning spam. No code changes this pass; nothing to port to dtsl2/dtslmud.

Test character (kept, saves are ordinary fresh-registration state): id ceshiq, Chinese name 测钱 (male), password Cq123456. State: newbie gift received (combat_exp 6015, +1 str/con/dex), 5 coin cash + 10 coin deposit, one sparring session at 石龙武馆's 练武场. Saves: work/data/user/c/ceshiq.o, work/data/login/c/ceshiq.o.

Cleanup

One native driver boot this pass (PID confirmed via readlink /proc/<pid>/cwd matching this lib's work directory before kill). Incidental data/login/f/fluffos.o + data/user/f/fluffos.o (admin save, pure key-reorder, no value change) reverted via git checkout -- before commit.

§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.