Ultimate Hell: Ai Ruo You Lan

✅ 可玩

终极地狱之爱若幽兰

zjdyaryl

🔑 fluffos / Mud@2026 更新 9a08edc 2026-09-04 源码 下载 ZIP

▶ 开始游玩 · Play Now

游戏登录后自报家门为"地狱泥潭---爱若幽兰"(压缩包标题为"终极地狱之爱若幽兰"),属于 ES II → XKX → "地狱"(Hell/Doing 血统)引擎家族,与 `hell`、`zjdy2008wzb`、`zjdywzb`、`zjdyzj`、`zjmudhell` 共六个档案共享同一个门派江湖世界(逐字节地图比对显示与 `zjdy2008wzb` 高达 95% 一致,与最近的姊妹版 `zjdyzj`(指间MUD版)也有 94% 一致——两者 master 文件内容几乎完全相同,与 `zjdywzb`、`zjmudhell` 则更疏远、约 73-79%),是同一份原作世界反复重制的六个版本之一而非各自独立的游戏;与 `zjdyzj` 不同,本作保留了普通 telnet 注册流程而没有接入手机客户端专属协议层,也和名字同样带"终极地狱"字样、但内容完全不同的 `zhongjidiyu` 没有任何关系,只是名字碰巧相似。

English

Introduces itself in-game as 'Hell's Quagmire — Ai Ruo You Lan' (the archive's own title is 'Ultimate Hell: Ai Ruo You Lan'). Part of the ES II to XKX to 'Hell' branch of the engine family, and part of a six-way 'Hell'/Doing-lineage map family with this collection's hell, zjdy2008wzb, zjdywzb, zjdyzj, and zjmudhell — a byte-level, line-ending-normalized room-tree comparison found it 95% identical to zjdy2008wzb and 94% identical to its closest sister zjdyzj ('Fingertip MUD' edition, sharing the same 'Hell' engine core down to near-identical master-file content), with that same map only ~73-79% identical to zjdywzb/zjmudhell — one shared authored wuxia world reused across all six builds, not a handful of coincidentally similar titles. Unlike zjdyzj, this build keeps a plain telnet registration flow rather than a mobile-client protocol layer. Not the same game as zhongjidiyu, another archive in this collection that also happens to carry 'Ultimate Hell' in its name.

README

内容亮点

在线试玩

https://mudlibs.fluffos.info/zjdyaryl/

管理员账号 / Admin account

警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改这两个密码。

本地运行

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

游戏端口:40073

NOTES · 移植与修复记录

终极地狱之爱若幽兰 (Ultimate Hell: Love Like Orchid) — archive #79

Source archive: archives/终极地狱之爱若幽兰1.166正式版.rar Slug: zjdyaryl (matches the archive title; no discrepancy — the config's own name field is №㊣地狱泥潭---爱若幽兰㊣№......, i.e. "地狱泥潭" (Hell Nitan/Swamp) + "爱若幽兰" (Love Like Orchid), matching the archive title exactly). Port: 40073.

Real mudlib root: the archive's top level is 终极地狱之爱若幽兰1.166正式版/, containing:

Lineage: confirmed ES II → XKX → "hell" fork via adm/single/master.lpc's own header credit chain: "for ES II mudlib / original from Lil / rewritten by Annihilator (11/07/94) / modified by Xiang for XKX (12/15/95) / updated by Doing Lu for hell (2K)", and adm/daemons/securityd.lpc's matching "Modified by Xiang for XKX / Updated by DOing Lu for ULTRA HELL". Same adm/single/{master,simul_efun}.lpc + adm/daemons/* "Century"-style layout as es1_win/esI/xkx2001/rzrmud/bmxkx2001/ kxkj/yueyingqiyuan/wuhanzhan/yanhuangwuhun/haiyang2/ kxkj1/xuanjianlu/shenzhou/shenmo. NOT related to the nitan/NT/Lonely lineage despite "泥潭" appearing in the display name — that word is just part of this fork's own branding ("Hell Swamp"), not a signal of the NT/nitan/Lonely engine family; confirmed via feature/ dbase.lpc (real local set/query/delete methods, not the bare simul_efun dbase-sharing architecture bug of §15).

CROSS-CHECK FLAG for the main session: archives #78 (终极地狱.rar) and #80 (终极地狱-指间mud版服务端.rar) share the "终极地狱" name and were being processed by sibling agents concurrently with this one — could NOT cross-check lineage/duplication against them here. Per this project's repeated experience (documented many times in TODO.md — sjpl2 vs shujian2008, xianlvqiyuan vs xlqy_new2007, kxkj1 vs kxkj, etc.), similar/identical Chinese titles are NOT a reliable lineage signal — verify via diff/md5sum on core files (master.c, chinese.c, securityd.c, logind.c) once all three archives are done, rather than assuming they're the same game or unrelated just from the shared name.

Fixes applied

Proactive (applied before first boot, from the AGENTS.md catalog)

1. §15h is_chinese() (adm/simul_efun/chinese.lpc) — GBK byte-range check (str[i] < 176 || str[i] >= 248, paired-byte loop) replaced with a CJK Unified Ideographs codepoint range check (0x4e00..0x9fff), one character per index. Standard fix; this WAS the blocker for real registration in every earlier-processed lib until §15h was discovered. 2. §15h deep named.lpc fix (adm/daemons/named.lpc) — this lib has the full "nitan-family-shaped" deep pattern despite not being nitan lineage: - PATH(name) macro: name[0..1] (first GBK byte-pair) → name[0..0] (first character). - strlen(name) < 2 (×3 call sites: remove_name, who_is, invalid_new_name's initial null-check) → strlen(name) < 1. - invalid_new_name's combined-length gate strlen(name) < 4< 2. - Sliding-window substring checks: name[i..i+3] (4-byte/2-char window) → name[i..i+1]; name[i..i+5] (6-byte/3-char window) → name[i..i+2]; loop bound i <= l - 4i <= l - 2; inner guard i + 6 <= li + 3 <= l. 3. §15h logind.lpc check_legal_name — byte-width bound maxlen halved (strlen(name) > maxlen> maxlen / 2; lower bound < 2< 1), plus the separate combined surname+given-name length check (strlen(fname) < 4< 2) in get_name(). Both match the in-game prompt text exactly ("不要超过两个汉字" = max 2 characters; "姓和名的组合至少要有两个汉字" = combined min 2 characters). 4. §14 valid_override 3-arg upgrade (master.lpc) — added the main_file parameter and an main_file == SIMUL_EFUN_OB/MASTER_OB check, insurance for any efun::-override fragment #included into simul_efun.lpc/master.lpc rather than being that file itself. 5. §8d/§15o get_include_path() (master.lpc) — was completely absent; added the standard "prepend the compiling file's own directory" implementation so mid-connection lazy compiles of any same-directory #include resolve correctly (compile-time-only/preload compiles already work via the config's include directories, but a live compile triggered from inside a connection needs this apply). 6. §15n securityd.lpc custom-ACL allowlist — this lib has a genuinely custom exclude_read/trusted_read ACL (not the simpler find_object(SECURITY_D)-only master.lpc pattern), so added the standard switch(func) { case "load_object": case "recompile_object": case "include": return 1; } early-allow to valid_read() before any euid/status logic — compiling/including code should never be gated by a fresh, not-yet-authenticated connection's (player) ACL status. 7. §15p dns_master preload exclusion/adm/daemons/network/ dns_master was present in adm/etc/preload; commented out (the master.lpc's own update_file() already strips #-prefixed lines, confirmed by reading it before relying on the comment-out). 8. §15ae command_hook private bugfeature/command.lpc declared its central add_action dispatch hook as private nomask int command_hook(string arg). This driver treats private as hidden from add_action's external dispatch once inherited into another object (the player body class here) — would have silently broken every post-login command (including look) with zero visible error anywhere. Dropped private, kept nomask. Confirmed via testing this was the single most important fix — verified look/score/i all actually dispatch and produce real output, not silence. 9. §15w log_error() warning-spam gate (master.lpc) — applied proactively as insurance: gated the player-facing broadcast (efun::write/tell_object) on the message NOT containing "warning:", so ordinary compile warnings (e.g. the nosave-function warnings from fix #10 below) don't spam a connected wizard-level player during any lazy compile. Everything still gets logged to /log/log unconditionally.

Found reactively (boot + lpcc sweep)

10. §3 staticnosave blanket sed, and its counterexampleconvert_lib.sh's automated pass touched 128 files. As expected from the moniHuafu precedent, this lib ALSO uses a "static/xxx" naming convention extensively — both as log_file("static/XXX", ...) paths (a REAL /log/static/ directory ships in the raw archive) and as dbase property-key namespacing (->query("static/marry"), ->query("static/sadly"), etc — internally self-consistent either way, but reverted anyway for clarity/no-surprises). Found 51 files with "nosave/... string-literal corruption after the sed; reverted all of them back to "static/... with a scoped quote-anchored sed ("nosave/"static/), verified zero remaining "nosave/ hits afterward. feature/treemap.lpc's nosave nomask (originally static nomask) function declarations compile fine — no ordering/collision issue there. 11. §15s message()-wrapper crash (adm/simul_efun/message.lpc) — the local message(mixed arg, string message, mixed target, mixed exclude) override forwarded straight to efun::message(...), but tell_room()'s common 2-arg form (tell_room(room, msg), no exclude) leaves exclude at its varargs default of raw int 0, which this driver's real message() efun rejects (Expected: object, array, Got: int(0)). This crashed every do_channel() broadcast at preload time (channeld.lpc → message() → simul_efun's message()) — 8+ daemons hit it during preload alone (natured, punishd, storyd, eventd, memoryd, backupd, ftpd, cpud, questd). Fixed once at the shared root: normalize exclude to ({}) when it's neither an object nor an array before delegating to the real efun. Confirmed fully resolved — zero Bad argument 4 to EFUN message() errors in a fresh boot after the fix (down from ~10 per boot before it). 12. §2 .c.lpc rename-width bug ([0..<3][0..<5]) — found 5 genuine sites (all listing/stripping a *.lpc-glob'd filename's extension): adm/daemons/storyd.lpc, adm/daemons/eventd.lpc, adm/single/importer.lpc (one of its two [0..<3] sites — the sprintf("...item/%c/%s", ..., item_name[0..<3]) one, explicitly commented "去掉后面的 .c 字样" / "strip the trailing .c"), and adm/npc/luban.lpc (2 sites, both stripping a player-built room's .lpc filename before a DBASE_D->clear_object() call). Left alone: importer.lpc's OTHER [0..<3] site inside get_user_list() — that one strips a DIFFERENT, unrelated (2-char, .o-shaped) save-data filename extension, not something our .c.lpc rename touched; it's part of a legacy migration tool not on the registration/gameplay path, so left as pre-existing (possibly already buggy, out of scope). 13. §15b is_killing() type mismatches (direct calls passing an object where the function declares string id, only caught by this driver's static type checker on DIRECT calls, not ->-based call_other): - clone/user/user.lpc's accept_kill(object ob)is_killing(ob)is_killing(ob->query("id")). This is the player body class — broke make_body() silently, exactly matching this bug's documented signature (registration completes through gender selection, then the character never actually lands, with zero visible error). Confirmed by testing: after the fix, both test runs reached the actual starting room. - d/city/npc/guidao.lpc's ask_me()is_killing(who)is_killing(who->query("id")) (a quest/story NPC, not on the critical registration path, but fixed anyway since it was found via the sweep). 14. New §8g-shaped shared-root bug: inherit/misc/quest.lpc's set_information() parameter too narrowly typed — declared void set_information(string key, string info), but QUEST_D's own real set_information(object qob, string key, mixed info) already accepts (and many quest files pass) a function pointer (e.g. set_information(NPC_NAME, (: ask_npc :))) as the "info" — this thin wrapper's own narrower string info parameter rejected every such call with Bad type for argument 2 ( string vs function ). Fixed at the single shared root (info retyped mixed), resolving 7 quest clone files at once: supply, explore, capture, deliver, judge, shen, search. 15. Genuine pre-existing typos found via the lpcc sweep (none related to encoding/rename — confirmed by checking the raw archive): - inherit/condition/damo.lpc had two independent bugs in one file, both cascading into confusing-looking downstream noise: (a) line 215, return name + HIM "发作身亡了; — missing closing " before the semicolon. This single dropped quote swallowed ~13 lines of subsequent code as string-literal content, surfacing as a "syntax error, unexpected L_IDENTIFIER" at a COMPLETELY different line (228) and "Illegal character 0xe9/0x95/0xbf" errors at yet another line (281) that are actually perfectly valid UTF-8 bytes for 长/长/的/吁 — pure lexer-desync fallout from the one missing quote, not real illegal-character bugs (matches §9/§10's documented cascading-noise pattern exactly). (b) line 228 itself, independently: intp(cnd["remain"] || ! stringp(cnd["id"])) was missing a ]intp() was being called with a whole boolean OR-expression as its argument instead of just cnd["remain"]; fixed to intp(cnd["remain"]) || ! stringp(cnd["id"]). Fixing both resolved this file plus its 3 sibling clones (kungfu/condition/ damo_luanqi, damo_shangshen, damo_zheyuan, all of which inherit it) — 4 files from 2 bugs in 1 shared file. - kungfu/class/generate/girl.lpc:579query_per() called with 0 args where feature/attribute.lpc's int query_per(string arg) requires 1 (the parameter is never actually used in the function body, and every OTHER of the 5 real call sites elsewhere goes through ->query_per()/call_other, which this driver's strict arg-count check doesn't enforce the same way as a direct call). Fixed by passing 0 explicitly. - d/village/npc/obj/shoes.lpc — a set("icon","05047"); statement got accidentally interleaved mid-argument into a set("long", ...) call (set("long", \n set("icon","05047"); \n"这是...");), splitting one statement into a syntax error. Reordered so each set() call is complete on its own. - d/baituo/obj/bowl.lpc + d/baituo/npc/obj/bowl.lpc (identical duplicate content shipped in two different zone directories) — set_name("海口大碗", "bowl") passed a bare string where set_name(string name, string *id) requires an array; fixed both to set_name("海口大碗", ({ "bowl" })).

Confirmed NOT needed (checked, absent)

Confirmed harmless, left unfixed (documented, not chased further)

Verification

Boot: ~/src/fluffos/build-debug/src/driver config.fluffos from libs/zjdyaryl/, port 40073. Clean boot, Accepting telnet connections on 0.0.0.0:40073. Initializations complete. — zero fatal errors, only the one known-harmless versiond.lpc socket_bind() line in debug.log (present on every boot, before and after all fixes).

Full registration + post-login flow, verified in two separate driver sessions, each a SINGLE continuous mudclient.py connection:

lpcc_check.sh sweep: 7303 total .lpc files. First pass (before sweep-driven fixes): 7272 pass / 31 fail (99.6%). After fixing the genuine bugs found (damo.lpc ×2, quest.lpc shared-root, girl.lpc, guidao.lpc, shoes.lpc, bowl.lpc ×2): 7289 pass / 14 fail (99.81%) — the remaining 14 are all confirmed-expected noise (11 story-daemon self-destruct-when-no-players files + 2 DNS/intermud config-ID-mismatch daemons + 1 legacy importer with no diagnostic), documented above, none of them real bugs worth fixing.

Driver was launched via Bash's run_in_background-equivalent (setsid nohup ... & disown) each time and killed by exact PID after each test — no pkill -f pattern used.

Status for TODO.md

playable / done — full registration + post-login command flow verified end-to-end twice, 99.81% lpcc pass rate, zero unexplained debug.log errors. Cross-check against archives #78/#80 flagged above for the main session once all three are complete.

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

WASM-enablement pass (2026-07): loopback gates + admin seeding

Standard pass per AGENTS.md §1.3b/§1.3c/§1.3e/§1.5:

WASM long-sit boot-watch pass (2026-07)

200s scripts/wasm_boot_watch.sh sit: ftpd.lpc/versiond.lpc sockets-absent preload errors match the already-documented §1.3c class (caught by master.lpc's preload catch(), cosmetic); versiond compile-and-fail recurs twice in one boot (two separate unguarded callers reach load_object), same known class, harmless. Proactively ported two fixes found live on sibling zhonghua2 (shares the identical inherit/item/combined.lpc and adm/simul_efun/object.lpc byte-for-byte): dropped private on combined.lpc's destruct_me() (call_out-self-invocation denied under private→DECL_HIDDEN inheritance, so spent-down money stacks never self-destruct), and fixed object.lpc's file_owner() (return namereturn dir, misattributes 3-level-deep /u/<wiz>/<subdir>/<file> log_error writes). Neither fired visibly in this lib's own sit. Retest: fresh registration (id arysanb) into 世外桃源, look/quit clean, no regressions.

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

'hell'/Doing-Lu 引擎基础版。状态已从过时的 limited 修正——本轮修复了一个真实的 bug:clone/user/login.lpc 的 query_save_file() 只防范了 id 不是字符串的情况(!stringp(id)),没有防范空字符串的情况——对 "" 取 id[0] 会回传整数 0,而 sprintf 的 %c 格式会拒绝这个值('Incorrect argument to type %c, must be valid UTF8 char'),在任何 id 被输入之前,第一次自动呼叫 query_save_file() 就会崩溃(每一次连线尝试都会现场触发,把 id 提示搞坏)。已通过额外检查 id == "" 修复(手足档案 zhongjidiyu(052)和 zjdyzj(054)上也应用了同样的修复)。修复后重新验证管理员登录(fluffos/Mud@2026)干净正常,'目前权限:(admin)',quit 正常。

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

深度功能测试 / Deep functional test (AGENTS.md §10.7)

Native driver only (~/src/fluffos/build/src/driver, -DPACKAGE_DB=OFF ASAN/UBSAN preset), booted from the lib root (libs/zjdyaryl/, port 40073) per §5.2. Client: scripts/mudclient.py (raw-socket, single continuous connection per invocation) — scripts/tmux_mud.sh was tried first but this container has no telnet binary at all, so every session below is a mudclient.py invocation carrying the full send-sequence in one shot (one TCP connection = one continuous session).

Pre-boot environment gotcha (not a code bug)

First boot in this container hit *Wrong permissions for opening file /log/log for append. "No such file or directory" (spammed once per preloaded daemon, caught by master.lpc's own catch(), non-fatal) — neither libs/zjdyaryl/log/ (lib-root, for debug.log itself, driver CWD-relative per §5.2) nor libs/zjdyaryl/work/log/{static,user}/ (mudlib-virtual-root, for log_file()/assure_file() targets like clone/user/login.lpc's log_file("static/logon", ...)) existed yet in this fresh container — both are gitignored runtime directories that a prior pass's WASM-enablement notes assumed were already present. Created both (mkdir -p log log/static log/user, lib-root and work/ respectively) before the real test boot; zero Wrong permissions lines in every subsequent boot. Not committed (gitignored), noted here so a future dive in a fresh container doesn't misread the same symptom as a regression in the already-fixed log_file()/assure_file() pair (adm/simul_efun/file.lpc's log_file() genuinely still lacks its own assure_file() guard, matching this lineage's known §7.11 shape, but every actual call site either goes through an already-assure_file()d caller — e.g. channeld.lpc — or targets a directory that exists once the above mkdir -p is done; no live crash reproduced from it this pass).

Newbie material

clone/misc/newbie.lpc("新手必读") is a read bookHELP_CMD->main(me, "feature") pointer, but the real onboarding path is entirely NPC-driven: land in 世外桃源 (d/register/entry.lpc) → 水笙(shuisheng)'s greeting()/do_register() prompts register <email>decide → walk to one of 4 personality-NPC rooms (east = 陆天抒/"光明磊落") → out → 阎罗殿(yanluodian.lpc) → wash (roll the 4 stats per chosen 猛士/智慧/耐力/敏捷/均衡 type) → born <地名> (e.g. born 扬州人氏) lands in a real starting city (/d/city/kedian).

Registration + state verification (two independent continuous sessions)

Combat mechanism

Read cmds/std/fight.lpc before testing, per this session's standing lead: confirmed the exact can_speak-gated split it was looking for — obj->query("can_speak") true → routes through obj->accept_fight(me) (decline-or-spar, "点到为止...不会真的受伤" per fight's own help text); false → unconditionally obj->kill_ob(me), a real fight. Default accept_fight() (inherit/char/npc.lpc) itself calls kill_ob() directly when !can_speak, so the split is enforced at both call sites, consistently — existing, intentional design, not a bug (matches the pattern already documented project-wide; did not test the non-can_speak branch against a live creature, by design, since that branch is genuinely lethal).

Live test: fight ouyang ke (欧阳克, a human/can_speak story NPC at 北大街) correctly invoked accept_fight() — declined in-character ("在下怎么可能是小兄弟的对手?" / "看起来欧阳克并不想跟你较量。") because its attitude is "friendly" and its qi/jing were both at 100% (inherit/char/npc.lpc's default accept_fight(): "friendly" + ≥75% qi/jing → decline). A real, clean exercise of the safe branch with a negative outcome — no damage, no crash, no error. (This same fight attempt is also what first reproduced the eval_function bug below, via combatd.lpc's post-fight-request start_call_out().)

Skill/sect acquisition — both paths

quit / reconnect / persistence

cmds/usr/quit.lpc has no new-account grace-period or delete-on-quit logic (checked before testing) — ordinary quit is always safe here, no need to simulate a raw disconnect instead. Existing design, not a bug: non-wizards get all non-equipped, non-autoload inventory dropped on quit (anti-hoarding-while-offline mechanic).

Bugs found and fixed

1. §8.3a addendum, 3rd confirmed instance: feature/action.lpc's eval_function() declared private. privateDECL_HIDDEN demotion-on-inheritance (this file is inherited into every character via inherit/char/char.lpc) silently blocks the call_out("eval_function", ...) dispatch that start_call_out() (this file's own general-purpose "run this function after a delay" primitive) relies on — 91 files across the tree call start_call_out(), including adm/daemons/combatd.lpc and 80+ kungfu/skill//kungfu/special/ buff/poison/powerup files. Reproduced live: debug.log showed apply() with insufficient permission: ... ob: clone/user/user#N, function: eval_function, origin: internal, needs: private, has: hidden immediately after an ordinary declined fight command (which schedules a combatd.lpc recovery callback via start_call_out()). Fix: dropped private (void eval_function(function fun) { evaluate(fun); }). Re-tested the identical fight decline post-fix, fresh boot: zero further eval_function/insufficient permission lines. Also fixed the identically-shaped clone/questob/letter.lpc:private void eval_function(...) for consistency — not confirmed live-triggered (nothing in that file actually schedules a call_out("eval_function" itself, so it may be dead code), but same bug shape, same trivial fix, zero risk. 2. §7.90, 5th confirmed instance (new lineage): maximum evaluation cost : 2000000 (config.fluffos) was too tight — not tripped by registration or movement, but by ordinary background daemon activity: adm/daemons/quest/capture.lpc's periodic heart_beat() spawning a kungfu/class/generate/capturenpc3 NPC whose randomly-chosen setup_family() branch (from_xueshan()) hit Eval interrupted: ... cost limit reached, limit: 2000000 usec mid-set_skill()/ACL-check, roughly 20 minutes into an otherwise-idle boot with no player nearby. Fix: raised to 5000000 (established §7.90 remedy value, already used by 30+ other libs). Verified: fresh boot + full replay of both registration sessions + the fight/apprentice/setsk tests above, zero further cost limit reached lines in debug.log.

发现但判定为既有设计、未改动的现象 (observations, not bugs)

WASM 未验证说明

Not re-verified under WASM this pass (native-only, per this project's current WASM build blocker). Confirm via: curl -sS "$HTTPS_PROXY/__agentproxy/status" — emsdk's storage.googleapis.com dependency is denied by the proxy, unchanged from every other lib checked this session. This lib's own prior WASM-enablement pass (2026-07, above) already covers WASM-specific gates (VERSION_D, messaged.lpc socket_bind, loopback allow); the two fixes in this pass (eval_function visibility, eval-cost ceiling) are driver-behavior-general and apply identically under WASM once it's buildable again in this environment.

深度功能测试第二轮 / Deep functional test round 2 (2026-08-15, post driver-upgrade re-test)

Round-two re-verification against the current native build-debug driver (post-upgrade — pulls in PRs #1343/#1344 and the corpus-wide %-operator float-crash fix). Standard checklist + live playthrough-style verification. The prior pass's own reconnect test only covered the link-dead/wall-clock- gap path, not the kick-duplicate-login confirmation path — this round adds that.

Findings:

1. AGENTS.md §7.107 (adm/daemons/closed.lpc's load_all_users() calling login_ob->restore()/user_ob->restore() with no catch() guard): a corrupted closed-cultivation account's save data would throw uncaught, aborting the whole heart_beat() tick before the cleanup (destruct()+map_delete()) runs, and retrying forever. Fixed by wrapping both restore() calls in catch() with an ok flag, same pattern as the other confirmed instances of this class this window. 2. AGENTS.md §7.108 (clone/user/user.lpc's reconnect() missing enable_commands()): confirmed active LOGIN_D (adm/daemons/logind.lpc) calls user->reconnect() on the character body after exec(old_link, user). Fixed by adding enable_commands(); as the first statement. Live-verified with two concurrent telnet sessions: session 2 logged in as fluffos (this lib's regular login password Mud@2026), confirmed the "赶出去,取而代之吗?(y/n)" prompt with y, and the resulting session correctly dispatched look (real room description). score returned "还没有出生呐" — expected content-gated response for this still-unregistered admin account (not a bug; same pattern as previously confirmed on sibling lib xkxz2), confirmed harmless by cross-checking with look. 3. adm/simul_efun/file.lpc: log_file() never called assure_file() before write_file(); added the call (plus a forward declaration). cat()'s write(read_file(file)) had no null-guard; changed to write(read_file(file) || ""). 4. Already correct, no change needed: cmds/wiz/update.lpc already guards with environment(me) &&. adm/single/master.lpc's log_error() already uses the case-agnostic "arning:" filter (AGENTS.md §7.10). maximum evaluation cost was already 5000000 (raised in an earlier pass per this NOTES.md's own §8.3a section).

Live verification summary: booted the native driver on port 40073 (the known-harmless, previously-documented versiond.lpc socket_bind() argument-type error fired again at boot as expected, non-fatal; Initializations complete / Accepting telnet connections both printed). Logged in as the seeded fluffos admin (Mud@2026), confirmed real write access via update /adm/simul_efun/file (recompiled successfully). Ran the two-session kick-duplicate-login reconnect test described above and confirmed the §7.108 fix live — this specific path (distinct from the link-dead reconnect this lib's earlier passes already covered) had not been exercised before. No new error classes in log/debug.log beyond the known versiond/boot-time line. Killed the driver by exact PID when done.

本轮修改的文件 / Files modified this round:

AGENTS.md §7.100 fix (2026-08-19): redundant replace_program(ROOM) landmine

Same corpus-wide bug as the batch-1-6 sweep (ROOM macro "/inherit/room/room" from include/globals.h). Deleted 2,315 live standalone replace_program(ROOM); lines under work/ via fix_710_room.py, plus hand-fixed the room-building tool's string-builder template (work/clone/misc/roommaker.lpc). No .lpc files under work/data/, so no false-negative risk. Remaining matches after the fix are all pre-existing //-commented.

Verified: clean build-debug boot (zero new compile errors, zero "cannot replace"/"cannot bind" in debug.log), live admin login (fluffos/Mud@2026) into the game world, look/quit worked cleanly (score's "还没有出生呐" is pre-existing admin-account behavior). Incidental data/{login,user}/f/fluffos.o save drift from the login test was reverted via git checkout HEAD before committing.

§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): 5 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.

深度功能测试(2026-09-04,round three,shop + 拜师)

新角度:扬州醉仙楼购物 + 丐帮李斧头拜师。round one 只测了 apprentice ouyang keborn_family 拒收(「你不是我们欧阳家的人」),没有真实 收徒,也没有商店购买。round two(2026-08-15)只补了 kick-duplicate 重连。 sibling zjdy2008wzb 2026-08-19 已经走过华山店 buy jitui + bai li futou

本轮没有新的 programming bug。enter_world() 已经是 ob->set("registered", user->query("registered"))(从 user 抄到 login, 和 xkxz2 Bug 2 方向相反)。log_file() 已有 assure_file()log_error() 已有 arning: 闸门。env/prompt"null",不是每秒时钟。

实测过程

管理员 fluffos / Mud@2026 / 浮云。第一输入是「您的英文名字」,没有 BIG5 提示。端口 40073。连线有大量 Tomud 控制码(licon/lbadd),不影响 指令派发。is_admin()VERSION_D->is_release_server() || admin_flag == 1222,本环境 is_release_server() 为真,clone /clone/money/gold 一次成功。

原先 registered:0score「还没有出生呐」。走完 register [email protected]decidewest/out(阴险奸诈)→ washborn 扬州人氏,落地扬州客店。born 后弹出游戏规则 pager(ENTER/q), 下一条指令被 pager 吃掉,不影响后续 clone

goto /d/city/zuixianloulist 包子五十文 / 烤鸡腿八十文 / 烤鸭一两 白银又五十文 / 牛皮酒袋一两白银。扬州店小二没有丐帮穷叫化踢人。 buy jitui 成功。i 剩九十九两白银 + 二十文铜钱(10000−80 = 9920)。

goto /d/gaibang/underhs(舍身崖下),李斧头 id li / kungfu/class/gaibang/li-futou.lpc,只收男性。apprentice li 一次成功: 「恭喜您成为丐帮的第二十代弟子。」score「丐帮第二十代传人」、师父李斧头。 save.lpc 真正双存。

save 后不 quit 丢 socket(此时 user.o registered:1login.o 仍是 0),重启驱动强迫走 enter_world()。重连落地客店而不是世外桃源, 注意事项是普通欢迎而不是「您还没有注册」,score 仍是丐帮二十代 / 李斧头 / 扬州人氏,银子铜钱还在。烤鸡腿是 F_FOOD,不进 autoload,重启后不在 身上——不是存档 bug。

live debug.loglibs/zjdyaryl/log/debug.log(Boot Time Fri Sep 4 03:32:59 2026),无 error: / Too deep recursion。mudlib work/log/log 只有开机编译警告。管理员存档未提交。