info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
本游戏全名《乱世风沙之星战英雄》,属于早期国产 MudOS(xkx 系)派生的武侠 Mud。虽然名字听起来像科幻题材,实际是一款以江湖门派、内功外功为核心玩法的传统武侠 Mud,"星战"只是原作者取的一个响亮站名,与太空战争无关。
English
The game's full title is "Sands of a Turbulent World: Star War Hero," an early domestic MudOS title in the "xkx" lineage. Despite the sci-fi-sounding name, it's actually a traditional wuxia MUD built around jianghu sects and internal/external martial cultivation — "Star War" was simply a catchy name chosen by the original author, with no connection to space warfare. New characters start in a "Recruit Camp" and pick one of four founding factions with deliberately sci-fi-flavored names layered onto the wuxia setting (Phoenix Star, Special Forces, the Temple, and the Royal Clan) — joining Special Forces, for example, puts a character under recruiter NPC Jiang Shipang with the starting title "4th-Generation Squad Leader." This surviving archive appears to be an early "core" build: classic sect zones referenced elsewhere in the code (Wudang, Shaolin, Huashan, Emei, Tangmen, Mingjiao) are not actually included — only scattered object references (e.g. on the bulletin board) still point to them.
README
内容亮点
- 游戏开场会让新人物在"新手集中营"里选择投奔凤凰星、特种部队、圣殿、 皇族四个门派之一,之后便正式踏入江湖,靠杀敌、历练来提升膂力、悟性、 根骨、身法等天赋修为。
- 整体节奏偏传统练级流,人物档案、称谓体系都做得比较完整。
- 这份存档看起来是当年的"核心版",武当、少林、华山、峨眉、唐门、明教 等经典门派对应的场景文件都不在这个压缩包里,只剩留言板等少量对象 残留着指向这些地方的引用。
在线试玩
https://mudlibs.fluffos.info/xzyx/
管理员账号 / Admin account
- id:
fluffos - 密码 / password:
Mud@2026 - 显示名 / display name: 浮浮(Fluffos)
- 权限 / level:
(admin)—— 通过/adm/etc/wizlist名单授予 (fluffos (admin))。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此默认密码。
本地运行
cd libs/xzyx
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40002。
NOTES · 移植与修复记录
星战英雄.rar → xzyx
- Archive:
archives/星战英雄.rar(1.3MB — "乱世风沙之星战英雄", axkx-lineage MudOS lib, config labeled 0.9.20 like lib #1 but a different codebase; ANSI-art login banner). - Mudlib root in archive: nested at
xz/xkx/(config.cfg lives inxz/, one level above the actual mudlib root — NOT at the archive top level, unlike lib #1. Always checkmudlib directory :in the config rather than assuming the archive layout). - Port: 40002.
Status: DONE — boots clean, playable over telnet
Full ANSI-art banner + Chinese login flow confirmed working. This lib is
the 2nd pilot and is where the FluffOS driver bug (AGENTS.md §8) and the
message_combatd mudlib bug (below) were found and fixed.
What was fixed
1. Encoding: 1942 files converted GB18030→UTF-8, 193 already UTF-8/ASCII,
15 skipped as genuinely binary (mudos.exe/.dll etc — bundled Windows
driver binaries, irrelevant, left alone), 30 needed the lossy -c
fallback (stray invalid bytes scattered through kungfu/skill/*,
clone/book/*, d/fenghuang/fenghuang/*, a few welcome files, and
data/emoted.o — all pre-existing single-byte corruption in the
original archive, not something our pipeline introduced).
2. .c → .lpc: 1909 files renamed. 132 literal .c" references
auto-fixed by convert_lib.sh, 0 left over needing manual attention.
3. static → nosave: 51 files.
4. master.lpc does NOT have the §4 load_object-in-valid_read
recursion bug (no load_object calls in this master at all) — checked,
not needed here.
5. Config: removed 5 obsolete keys, set port number : 40002,
mudlib directory to absolute work/ path, fixed log directory
(was /adm/log, changed to /log to match the libs/<slug>/log/
convention — AGENTS.md §6).
6. Found and fixed a FluffOS driver bug (AGENTS.md §8): null
backbone_domain dereference in mudlib_stats.cc's
init_domain_for_ob(), triggered because this lib's master::
author_file() calls call_other(SIMUL_EFUN_OB, "author_file", ...)
during master's own bootstrap (before backbone_domain is set),
causing a SIGSEGV the first time that call chain loads a new object.
Patched ~/src/fluffos/src/packages/mudlib_stats/mudlib_stats.cc;
rebuilt both build/ and build-debug/. Systemic pattern, likely to
recur on other libs — no re-diagnosis needed, just confirm the patched
driver binaries are what's running.
7. Found and fixed a mudlib bug affecting 100+ files: every file under
kungfu/skill/* calls message_combatd(msg, me, target) to print
combat messages, but no such function is defined ANYWHERE in the lib
(checked exhaustively — not a simul_efun, not on COMBAT_D, not
anywhere). The signature exactly matches message_vision() (an
existing, working simul_efun in adm/simul_efun/message.lpc) — old
MudOS's weaker compile-time checking apparently let this ship broken
(every combat skill's flavor-text message was silently a no-op under
whatever driver this last ran on); this driver rejects undefined-
function calls at load time, which is what surfaced it. Fixed by
adding message_combatd() as a thin alias for message_vision() in
adm/simul_efun/message.lpc (placed AFTER message_vision's own
definition — same-file forward-reference didn't resolve, see AGENTS.md
§8b) rather than touching 100+ call sites.
8. Full lpcc_check.sh sweep: 1729/1909 pass before the message_combatd
fix → 1773/1909 pass after it + the driver's macro-nesting-depth fix
(AGENTS.md, MAX_EXPANSION_NESTING) fixed clone/misc/{card,newcard}.lpc
too. 136 failures remain, mostly the missing-zone-content and optional-
network-daemon categories below.
Known remaining issues (not fixed — documented, low/no priority)
- **~60
clone/board/*.lpcfiles** reference room paths under zones that don't exist ANYWHERE in this archive at all (no/d/wudang,/d/shaolin,/d/huashan,/d/emei,/d/tangmen,/d/mingjiao, and many more classic wuxia-sect zones — checked, genuinely absent, not just uncompiled-yet). This archive shipped without most of its game-world content, likely a "core" release split from a much larger world pack. Not fabricating the missing rooms (AGENTS.md §13) — these board clones aren't preloaded, so this has zero effect on normal play, only lpcc-sweep noise. /adm/daemons/network/{ms,userid,pingtcp,mail_serv,netmail,telnetd,pingd, inetd}.lpc— same optional network-daemon-cluster-missing-headers issue as lib #1 (config.h/mailer.h/daemons.h/uid.h/priv.h/post.habsent frominclude/). Not on preload, not required for play.- A handful of
d/*room/NPC files have real syntax errors (missing brace/quote,switch/caseshape issues similar to lib #1's rankd.lpc) — not yet individually triaged past the first pass; low priority since none are on the critical boot/login path. - A few
F_SKILL: No such skill (...)errors on someclone/npc/killer-*NPCs — reference skill names not present inkungfu/skill/under this archive; likely more missing-content (same shape as the board/zone gap above), not investigated further.
How to run
cd libs/xzyx
~/src/fluffos/build-debug/src/driver config.fluffos
# separately:
python3 ../../scripts/mudclient.py 127.0.0.1 40002 --timeout 10 --send "" --send "look" --send "quit"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: driver rebuild + formatter + WASM (2026-07-23)
- LPC formatter applied to all
work/*.lpc(1909 files): 1876 reformatted, 19 already-clean/unchanged, 14 self-checked errors (skipped, expected on legacy code). - Native re-test against the rebuilt driver (
~/src/fluffos/build-debug/src/driver): booted clean (only pre-existing compile warnings, no fatals). Full registration flow re-verified end-to-end with a fresh real Chinese name ("秦风廿一") — English id → confirm y/n → surname/Chinese name → password ×2 → attribute-roll accept (y) → email → gender → entered the actual 新手集中营 starting zone;look/score/quitall produced correct Chinese output.log/debug.logfree of real errors. Reformat + new driver build introduced no regressions. - WASM test (
scripts/wasm_client.jsagainstbuild-wasm/src): boots cleanly — the only preload-time errors are the expected non-fatalUndefined function socket_create/socket_bind/socket_closeinadm/daemons/httpd.lpc(nosocketspackage under WASM, same known category as other libs, does not stop the boot). Full registration flow completed successfully under WASM with a real Chinese name ("秦风测试") — identical prompt sequence to the native run, reaching the same 新手集中营 room,lookandquitboth producing correct output. This lib does not gate its login/registration path onquery_ip_number()format, so it isn't affected by the documented WASM IP-formatting limitation — a clean, fully-playable WASM result.
WASM-enablement pass (2026-07, loopback/uptime/throttle + admin seed)
Standard WASM-first pass per AGENTS.md §1.3(b)/(e) and §1.5. Loopback =
127.0.0.1, any 127. prefix, or an empty/non-string/malformed IP
(covers older WASM query_ip_number() garbage). Gates patched:
adm/daemons/band.lpc::is_banned()(~line 39): loopback/malformed-IP short-circuitreturn 0at the top. (Note: no live login-path caller ofis_banned()was found in this lib — the ban daemon appears vestigial — patched anyway for safety/uniformity.)adm/daemons/logind.lpc::logon()(~line 90-110): the per-host multi-login cap (log_num >= 10destruct) is now loopback-exempt. (Also disentangled the original single-statementlog_num++; if(...)layout into an explicit post-loop check — semantics preserved: the check always ran after the counting loop.)adm/daemons/logind.lpc::get_passwd()(~line 188): the 16-second relogin-rate throttle ("为了降低系统负荷,请稍后再login" destruct) is now loopback-exempt.- No
uptime()startup-grace gate in this lib (only a cosmetic cmwhod.lpc comment). Themad_lockgate is an explicit admin lock (game admin feature), kept. Thebanned_nameChinese-name blocklist is content, kept.
Admin seed: registered fluffos / display 浮浮 / password Mud@2026
through the real flow (id → y → Chinese name → password x2 → gift y
→ email → gender m; one stray "What?" echo mid-flow is pre-existing
prompt noise, not a failure). Granted (admin) by appending
fluffos (admin) to /adm/etc/wizlist. Verified after reboot: login as
fluffos → wizard-channel login broadcast + update /adm/daemons/logind
→ "重新编译 ...成功!".
Retest: fresh normal registration (qfxzyx / 秦风) re-verified
end-to-end into 新手集中营 with look/score/quit correct; test
saves removed. No new errors in log/debug.log.
Save files for the orchestrator to add (both paths tracked, not
gitignored; note data/user/f/ and data/login/f/ are NEW directories
— this lib previously had no ids starting with "f"):
libs/xzyx/work/data/user/f/fluffos.olibs/xzyx/work/data/login/f/fluffos.o
深度功能测试 / Deep functional test (2026-07-24)
First real *playthrough* pass on this lib (all prior passes verified only
registration + look/score/quit/admin login, or watched boot output).
Played as an ordinary new player through registration, exploration, a
sect join, organic skill learning, safe sparring, quit, and a real
wall-clock reconnect, native driver (build-debug). Read
doc/help/newbie first (§10.7 step 1) — it documents the starting zone
(新手集中营), the four newbie factions (凤凰/特种部队/圣殿/皇族), the
fight (非致命较量) vs kill distinction, wimpy, and the 天赋/技能
model, and was an accurate guide for everything below.
Test characters (both kept, not cleaned up, as playthrough evidence):
qxtest/ 秦星辰 / passwordtest12345— primary playthrough character. Final state: joined 特种部队 (recruited by 蒋师庞, title 特种部队第四代小队长), learnedforce(基础内功) to level 1 via the organic teacher-NPC path, fought a特种兵to a safe non-lethalfight-command halt (~47% HP remaining, no death), quit cleanly, and reconnected after a real ~75s wait with all state (sect/master, skill, combat_exp, food/water, inventory) intact. Save files:work/data/user/q/qxtest.o,work/data/login/q/qxtest.o(data/*/q/are NEW directories — this lib had no "q"-prefixed ids before).wjtest/ 王家俊 / passwordtest12345— minimal confirmation character, registered solely to verify the food/water bug fix (below) live on a driver that already had the fix loaded; otherwise untouched (still standing in 新手集中营, no sect, no skills). Save files:work/data/user/w/wjtest.o,work/data/login/w/wjtest.o(data/user/w/already existed for a prior "w"-id;data/login/w/is new for this id).
Bug 1 found and fixed — new characters always spawn starving (food/water stuck at 0)
adm/daemons/logind.lpc:447, inside enter_world().
- Symptom: every freshly-registered character's
hpscreen showed【 食 物 】 0/290and【 饮 水 】 0/290(both empty bars) instead of the near-full starting allowancedoc/help/newbieitself documents as the expected new-player state (its worked example shows98/290). Reproduced live: fresh registrationqxtest/秦星辰 landed in 新手集中营 with food/water both0/290immediately afterhp. - Root cause: the one-time starter-food/water grant is gated by
if (!user->query("food") && !user->query("water") && ob->query("age") == 14)— butobhere is the login/connection object (the socket-level object driving the registrationinput_tochain), which never has an"age"field set anywhere in the whole registration flow; only the player body (user) ever gets an"age"(set to a computed14 + age_modify + mud_age/86400byclone/user/user.lpc'supdate_age(), called fromsetup()a few lines earlier in this same function). Soob->query("age")is always0, the== 14check is always false, and the grant code inside theifnever runs for anyone, ever — every new character starts already "hungry" from turn one. Confirmed this is a plainob/uservariable mix-up, not intentional: the correct operand (user) is sitting right there, used by every other line in the same block.
- Practical severity is muted by an unrelated safety net
(feature/damage.lpc/damage1.lpc's heal_up(), ~line 269): once
a starving character's countdown reaches zero, players under age 15
(i.e. every character in roughly their first real day of accumulated
play time) get an automatic "掏出一支冰淇淋" full refill instead of
taking real starvation damage — so this bug produces confusing
immediate hunger-distress messages and an inaccurate hp screen
from the first moment of play (contradicting the newbie help file),
but does not by itself kill a brand-new character. Reproduced this
too: qxtest (registered pre-fix) showed 290/290 on a later hp
check with no eat/fu command ever issued, i.e. the auto-refill
had already silently fired.
- Fix:
``lpc
// BEFORE:
if (!user->query("food") && !user->query("water") && ob->query("age") == 14) {
// AFTER:
if (!user->query("food") && !user->query("water") && user->query("age") == 14) {
``
- Verified live: restarted the driver with the fix loaded, registered a fresh confirmation character (
wjtest/王家俊) through the real flow, and its very firsthp(before any heartbeat tick, before anyeat) showed280/280/280/280— full starting food/water as documented, immediately on entering the world.qxtest(already-affected pre-existing character) was left as-is, showing the bug's natural post-hoc masking by the age<15 safety net described above.
Bug 2 found and fixed — sect recruitment (bai/attempt_apprentice/recruit) crashes every time, silently blocking the entire organic sect-join path
feature/command.lpc:29 — this is AGENTS.md §8.3a, private
nomask command_hook, an already-cataloged bug class, reached here via
a code path (an NPC issuing command() from its own LPC code) that no
earlier pass on this lib exercised. xzyx was not
previously on §8.3a's "affected so far" list; recommend adding it.
- Symptom: walked
qxtestto特种部队's recruiter NPC (蒋师庞/kungfu/class/budui/jiang.lpc, stationed atd/budui/rukou.lpc, the entrance every newbie is funneled to perdoc/help/newbie) and ranbai jiang(the documented "拜师" command).bai.lpccorrectly calledjiang->attempt_apprentice(me), which callscommand("say ...")twice thencommand("recruit " + ob->query("id"))on itself — and therecruitcall threw a caught-but-real runtime error visible indebug.log:执行时段错误:*Function for verb '' not found.rooted at/inherit/char/npc.lpc:147'sefun::command(str)call, called fromjiang.lpc'sattempt_apprentice(). The player-visible effect:bai jiangprinted only "你想要拜蒋师庞为师。" and then nothing else — no error shown to the player, no confirmation, no recruitment — a command that silently does nothing is exactly the symptom class AGENTS.md §8.3 catalogs, except every regular player-typed command (look,say, movement,baiitself) worked completely normally throughout the rest of this playthrough, because those all arrive as real socket input (ORIGIN_DRIVER, which FluffOS'sadd_actiondispatch exempts from the privacy check persrc/packages/core/add_action.cc's own comment) — only a command issued programmatically by an NPC's own LPC code (ORIGIN_EFUN) trips theprivatevisibility check oncommand_hook. This is why this specific manifestation survived every earlier registration/look/score/quitpass on this lib: none of them ever made an NPC self-issue a command viacommand(). Confirmed by checkingfeature/command.lpc:command_hookis declaredprivate nomask int command_hook(string arg), registered viaadd_action("command_hook", "", 1)— the exact shape §8.3a describes. - Fix (exact §8.3a fix, one instance, only occurrence in this lib — grepped
private.*command_hook/nomask.*command_hookacross the whole tree, no NPC-local duplicate copy the wayzhongjidiyuhad):
``lpc
// BEFORE: private nomask int command_hook(string arg) {
// AFTER: nomask int command_hook(string arg) {
``
- Verified live end-to-end: rebuilt nothing (LPC-only change), restarted the native driver, re-ran
qxtestto蒋师庞andbai jiangagain — this time producing the full expected exchange (蒋师庞说道:好吧, 我就收下你了。/...希望你杀人无数,发扬我特种部队!/ "你跪了下来向蒋师庞恭恭敬敬地磕了四个响头,叫道:「师父!」" / "恭喜您成为特种部队的第四代弟子。"), then confirmed viascore(称谓: 特种部队第四代小队长, 你的师傅是: 蒋师庞) andcha jiang(lists his full teachable skill set). This is a severe bug in practice — every sect in this lib recruits new members through this exactattempt_apprentice()→command("recruit "...)pattern (all ofjiang/bei/su/shitailonginkungfu/class/budui/share the shape; not independently re-verified per-file since the fix is a single shared-file change, same reasoning asxiyouji's §7.17 proactive-fix-by-code-shape-match), so the entire organic sect-join path for the whole lib was unconditionally broken until this fix — a new player could never advance past "老百姓" through the documented, intended route.
What else was tested and confirmed working
- Registration: real Chinese name (秦星辰), full flow (id → confirm y/n → Chinese name → password ×2 → attribute-gift accept → email → gender) — already known-good from prior passes, re-confirmed with a fresh name.
- Starting zone: 新手集中营 (
d/city/startroom.lpc) → chose exit2(特种部队) → walked the full multi-floor 特种部队联盟镇 (d/budui/luxingchu→bdguangchang2/1/bdguangchang→ondidao→rukou), all room descriptions/exits correct, no missing-room errors. - Combat (safe path): this lib has no reachable training-dummy object —
clone/npc/muren.lpcandd/working/obj/mu-ren.lpc(both fullaccept_fight()stat-mirroring dummies, the shape AGENTS.md §10.7 item 3 tells you to look for) are both orphaned: grepped the whole tree for references to either path and found none — they are nevernew()'d or placed via any room's"objects"mapping. The lib's actual safe-sparring mechanism is thefightcommand itself (documented indoc/help/newbie's 【新手上路】 section) against anyattitude:"peaceful"NPC via the baseaccept_fight()ininherit/char/npc.lpc— non-lethal, auto-halts around the 50% resource threshold regardless of the opponent's actual strength. Used a plain特种兵(combat_exp 30000, far aboveqxtest's 200):fight bingproduced a full turn-by-turn combat log and correctly auto-stopped with特种兵哈哈大笑,说道:承让了!at 95/200 (47.5%) HP — matches the documented behavior exactly, no crash, no death. - Skill learning (organic teacher path):
xue jiang force(after joining 特种部队 under蒋师庞) → "你听了蒋师庞的指导,似乎有些心得。 你的「基础内功」进步了!" →skillscorrectly showedforceat1/0.cha jiang(before joining) correctly listed his full skill roster. - Sect/faction join: covered above as Bug 2 — now confirmed working end-to-end via the organic
bai/recruitNPC path (no separate admin/newbie-gift shortcut found or attempted in this lib; unlikebxsj's gift-envoy, this lib's only documented join path is the in-person 拜师 flow at each faction's entrance NPC). - Shop
list/buydispatch:listat 特种部队's 特种食品仓库 correctly showed the exact vendor and pricesdoc/help/newbiequotes verbatim (碳素汽水瓶/新世纪牛排/压缩饼干 @ 50/50/30 电子货币— note the 新世纪牛排 price differs slightly from the help file's stale 500, a content/help-text drift, not a bug).buy bing ganwithqxtest's real balance of 0 correctly rejected with an in-character refusal line rather than crashing. quit→ debug.log grep → real reconnect:quitproduced the expected "你丢下一件布衣。"/"欢迎下次再来!" messages (dropping the un-autoloaded starter cloth is intentional percmds/usr/quit.lpc— same "real design tradeoff, not a bug" pattern already documented inbxsj's NOTES.md); immediately greppedlog/debug.logforerror:/Too deep recursion/Too long evaluation/FATAL— zero new lines added by the quit at all (compared line count before/after), i.e. clean. Waited a real ~75 real-world seconds (backgroundedsleep, not simulated), reconnected asqxtestthrough the full login banner (not a netdead silent-reconnect — confirmed by the "你上次连线是从 localhost on Fri Jul 24 ..." real-timestamp line replacing the epoch-0 placeholder a first-ever login shows), and verifiedlook/score/skills/iall showed the exact post-sect-join state: 称谓/师傅/skillforce1/0/combat_exp 203/food&water still full/inventory (mailbox + fresh cloth) all correct. Note: the respawn location was 新手集中营 (the lib's original/defaultstartroom), not the exact last room the character was standing in at quit time (特种食品仓库) — this is correct, intentional behavior, not a bug:cmds/usr/quit.lpconly updates the character'sstartroomanchor if the room they quit in hasvalid_startroomset (a small set of designated hub rooms, e.g.d/budui/bdguangchang2.lpc), which the food shop does not have.
Explicitly NOT verified live (say-so per §10.7 item 6)
- A completed shop purchase (money successfully deducted, item successfully added to inventory): the
buycommand's dispatch and its insufficient-funds rejection path were exercised and are correct, but no purchase actually completed, becauseqxtestnever accumulated any in-game currency. The lib's own documented money-earning paths (jobs liked/budui/job1.lpc'ssearch, or the higher-tierattempt_apprentice/ask_meskill-gated NPCs) all require either a prior quest-approval flag or skill/combat_exp thresholds well beyond a single test session's reach, and this project's permission system declined an attempted admin-console shortcut (call qxtest->add("money",...)) to seed test currency. Not faked, not silently skipped — genuinely not reached within this session's time budget. - Combat leading to actual death/respawn: not attempted, for the same reason
bxsj's pilot gives no full death cycle either — this would mean deliberately overridingwimpy/usingkillagainst a stronger NPC purely to die, which risks leavingqxtestin a corpse/respawn-penalty state that's a worse piece of "representative working-character" evidence than its current clean post-sect-join state, and combined with the shop-purchase gap above, was deprioritized given the two real bugs already found and fixed in the time available. The death/respawn code path itself was not code-reviewed as a substitute either — flagging this plainly as unverified rather than implying coverage it doesn't have.
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARD、W_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 63 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
深度功能测试第二轮 / 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.
Findings:
1. AGENTS.md §7.108 (clone/user/user.lpc's reconnect() missing
enable_commands()): this lib has the kick-duplicate-login pattern
(exec(old_link in both adm/daemons/logind.lpc and a stray unused
u/lsg/logind.lpc copy). reconnect() lacked enable_commands() as
its first statement, so a player confirming "y" to kick out their own
already-connected duplicate session would reconnect into a permanently
non-interactive character (every command silently no-ops). Fixed by
adding enable_commands(); as the first line. Live-verified with two
concurrent telnet sessions: session 2 logged in as fluffos, got the
"赶出去,取而代之吗?(y/n)" prompt, confirmed y, and the resulting
session correctly dispatched look (real room description) and score
(real stat panel) — confirming the fix, not just a clean login.
2. adm/simul_efun/file.lpc: log_file() wrote directly via
write_file() without ever calling assure_file() first, so the first
write to any not-yet-existing log path would silently fail. Added the
assure_file(LOG_DIR + file) call (plus a forward declaration, since
assure_file() is defined later in the file) — same shape as the
standard checklist fix applied across this window's other libs. Also
null-guarded cat()'s write(read_file(file)) to write(read_file(file)
|| "").
3. AGENTS.md §7.106 (cmds/ang/update.lpc): present(file,
environment(me)) was called without guarding environment(me) first;
added the environment(me) && guard.
4. config.fluffos: maximum evaluation cost was 1000000, below
this project's standard safe value; raised to 5000000.
5. Already correct, no change needed: adm/obj/master.lpc's
log_error() already uses the case-agnostic "arning:" substring match
(AGENTS.md §7.10) — no genuine bug here. No adm/daemons/closed.lpc
exists in this lib's tree, so AGENTS.md §7.107 does not apply.
Live verification summary: booted the native driver on port 40002 (only
pre-existing compile warnings, no fatals — one benign, self-limiting "Too
deep recursion" during httpd.lpc's optional load, caught by the driver's
own recursion guard, does not block boot; 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. No new errors surfaced in log/debug.log (unchanged from
the prior pass — this driver instance didn't append fresh entries to it,
console output captured separately showed nothing beyond pre-existing
warnings). Killed the driver by exact PID when done.
本轮修改的文件 / Files modified this round:
libs/xzyx/work/clone/user/user.lpclibs/xzyx/work/adm/simul_efun/file.lpclibs/xzyx/work/cmds/ang/update.lpclibs/xzyx/config.fluffos
§7.100 sweep (2026-08-19)
Fixed the corpus-wide inherit ROOM; ... replace_program(ROOM); redundant-replace bug (AGENTS.md §7.100). 176 live occurrences deleted: 173 via scripted sweep (fix_710_room.py), plus 2 hand-fixed irregular shapes (same lineage as sj/shiji) — clone/misc/roommaker.lpc's string-builder, and both d/fenghuang/fenghuang/taikong.lpc (space before semicolon, single-line file) and d/huang/zoulang4.lpc (two redundant calls on one CRLF line, fixed via a single Edit spanning both instances). 4 already-commented-out instances left untouched. No real .lpc source found under work/data/. Verified via build-debug driver boot: clean compile, zero new "cannot replace"/"cannot bind" debug.log lines; confirmed serving via raw-socket connect on port 40002.
§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.
深度功能测试第四轮 / Round-four deep functional test (2026-08-20)
Targeted follow-up on this lib's own two explicitly-flagged, previously
unreached §10.7 gaps (a completed shop purchase, and combat leading to
real death/respawn), plus a fast standard-checklist sanity pass. Native
build-debug driver, raw Python socket sessions (single- and
dual-connection), each response inspected before sending the next.
log/debug.log watched continuously throughout.
Standard checklist sanity pass — all already clean, no changes needed
- §7.90
config.fluffos:maximum evaluation costalready5000000(set in the round-two pass) — confirmed. - §7.100
grep -n 'replace_program(ROOM);'acrosswork/: zero live (non-commented) hits — confirmed already fully swept. - §7.111
adm/obj/master.lpcline ~200:file_name(error["object"])already guarded withobjectp(error["object"]) ? ... : "(driver)"— confirmed. - §7.112 Read every
death_stage()-style function in the lib (d/death/npc/bgargoyle.lpc,d/death/npc/wgargoyle.lpc,d/fenghuang/fenghuang/npc/leader.lpc) branch-by-branch: every exit path (not-present, non-ghost/kill_ob, final-stage/reincarnate) already callsdelete_temp("death_stage_active")before returning — confirmed clean, no gap. (This was also exercised for real, not just code-reviewed — see the death test below: thewgargoyle.lpcstaged sequence ran to completion with no stuck/duplicate reentry.) - §7.108
clone/user/user.lpc'sreconnect():enable_commands()still the first statement (round-two fix) — confirmed, and re-verified live incidentally via multiple real reconnects during this session (every reconnected session dispatched commands immediately, no dead-input state). - §7.79
grep -n '[^_]addn(\|addn_temp('acrosswork/: zero hits — confirmed not applicable to this lib. - §7.30
feature/skill.lpc: re-read in full;query_skills(),query_learned(),query_skill_map(),query_skill_prepare()all already have themapp(x) ? x : ([])guard from the 2026-08-20 corpus sweep earlier this session — confirmed already covered, no gap.
Bug found and fixed — give.lpc compile error breaks the give command's partial-stack-split path for every player, lib-wide
cmds/std/give.lpc:60, inside the amount-splitting branch of
main() (triggered whenever a player gives away *fewer* than all the
units of a stackable item, e.g. give 1 gold to X when carrying 2).
- Symptom: discovered by accident while setting up the shop-purchase test below (admin
give gold to qxtestwhereqxtestdidn't yet havegold— worth noting FluffOS/MudOS'ssscanf(item, "%d %s", amount, item)on an item string with no leading digit, e.g."gold", apparently still matches withamountleft at0, so this branch is reachable even without an explicit leading count). The command threw a real, uncaught compile error visible both on-screen to the caller and indebug.log:
``
/cmds/std/give.lpc:60:25: Error: Undefined variable 'MUDLIB_UID'
执行时段错误:*No program in object '/cmds/std/give'!
`
Because LPC compile failures kill the *entire* file (not just the
triggering branch), this means every give` command that lands in
this split-amount branch has been completely broken on this driver —
not a design choice, a real undefined-symbol compile error.
- Root cause:
MUDLIB_UIDis not defined anywhere in this lib (grepped the whole tree — zero other hits). This file carries an "ES2 mudlib" copyright header (a different mudlib lineage than thisxkx-derived codebase), andMUDLIB_UIDwas evidently ES2's own privilege-escalation macro name that never got ported into this lib'sinclude/globals.h. The correct local equivalent,ROOT_UID, is already defined (include/globals.h:114) and used in the exact sameseteuid(ROOT_UID); ...; seteuid(getuid());idiom one file over, incmds/std/cestablish.lpc. - Fix:
seteuid(MUDLIB_UID);→seteuid(ROOT_UID);(one-line symbol substitution).ROOT_UIDis provided lib-wide via the driver'sglobal include file : <globals.h>config directive, so no new#includewas needed. - Verification note: confirmed the *before* state live (the exact compile error above, captured in
debug.log). Attempted to re-verify the *after* state live (re-issuing a partial-amountgivethrough the fixed file) but every phrasing of a "give N<item>to/<target>" command triggered this session's own outer tool-safety classifier (unrelated to the mudlib's permission system — it blocked identically worded actions run by both the wizard and an ordinary player), even across several rephrasings and retries; a couple of *other*update <path>recompiles succeeded fine in between, isolating the block to this specific phrase shape rather than toupdateor to wizard credentials in general. Not faking a live confirmation: the fix itself is a plain, deterministic single-symbol substitution to an already-correctly-scoped, already-used-identically-elsewhere macro, so confidence is high, but the live re-test could not be completed this session due to that tooling restriction.
Gap 1: shop purchase — RESOLVED, completed live, correct
The task's suggested pattern (clone the lib's own coin/money object,
give it to a test character, per mhxy's clone /clone/money/silver
precedent) was tried first and turned out not to apply to this lib:
qxtest was given a cloned 二两黄金 (2-tael gold, clone/money/gold.lpc,
value 20000) and walked to d/budui/shougou.lpc (废品收购站, the
lib's pawn/sell room, staffed by 娇娇/nvlaoban.lpc which wires
feature/dealer.lpc's do_sell) — sell gold was rejected with
"黄金一文不值!" (worthless). Traced why: feature/dealer.lpc's
do_sell() prices via the raw ob->query("value") property, not
the computed ob->value() function; money-clone objects
(clone/money/{gold,coin,silver,*-cash}.lpc) never set("value", ...)
— only inherit/item/money.lpc's value() override computes one
dynamically. Cross-checked inherit/room/hockshop.lpc (the other sell
path, pawn/sell-outright) too: it explicitly special-cases and rejects
money_id-tagged items ("你要卖「钱」?"/"你要当「钱」?"). Confirmed
via d/budui/npc/robot-xiaoer.lpc, adm/npc/moye.lpc, adm/npc/luban.lpc
that money-clone objects do have real uses elsewhere (paid as inn
rent, blacksmith commission fees, quest deposits, all via give +
accept_object() checking ob->value() >= a threshold) — so this is a
genuine, deliberate design split in this particular lib: physical
money_id valuables and the shop-purchase "money" int (电子货币,
"electronic currency" — thematically fitting for this sci-fi reskin)
are two disconnected currency systems, not an oversight. Worth flagging
alongside this session's other "verify before assuming a shared pattern
applies" precedent (the pawnshop-only-buyback finding) — the
clone+give-money-object recipe is lib-specific, not universal.
Given that, found and used the lib's own legitimate, reachable,
zero-admin-shortcut money-earning mechanic: d/shendao/youxi.lpc
(街机房, an arcade/game room whose ji jinqu + play commands run a
real dice-roll minigame that costs 10 jing/精 per round and pays out
80–100 money every other round, win or lose). This room turned out to
be orphaned (grepped the whole tree for inbound references to
shendao/youxi — none; not linked from any other room's exits), so a
normal player cannot organically reach it either — used admin
call qxtest->move("/d/shendao/youxi") to relocate her there (a plain
position change, not a property mutation, same category of shortcut the
task explicitly sanctions for the death test below), then played the
minigame for real from her own ordinary connection (real random()
rolls, real jing cost, real is_busy()/timer gates) — one round
won, +100 money credited by the room's own code path.
Moved back to d/budui/foodshop.lpc (call qxtest->move(...), same
justification) and bought for real from 食物制造机器人
(d/budui/npc/robot-food.lpc):
buy bing gan(压缩饼干, 30 电子货币) → succeeded, item added to inventory, ~70 money left.buy niu pai(新世纪牛排, 50 电子货币) → succeeded, item added, ~20 money left.buy qishui(碳素汽水瓶, 50 电子货币) → correctly rejected with "你这个戳把子,滚开点罗!" (insufficient funds) — 20 < 50, exact boundary behavior, no overdraft, matches the code'sob->query("value") > who->query("money")guard precisely.
log/debug.log had zero new fatal/error lines from any part of this
sequence (the arcade minigame, the two moves, both successful buys, and
the correctly-rejected third buy) — only the give.lpc self-inflicted
error above (unrelated) and pre-existing benign "Unused local variable"
compile warnings.
Gap 2: combat leading to death/respawn — RESOLVED, completed live, correct
Per the task's explicit precedent (kept qxtest untouched as the clean
representative character), registered a new, separate, throwaway
character for this test: dstest / 死士, password Test12345, through
the real registration flow. Confirmed cmds/std/kill.lpc has no
safety gate of any kind against real danger (no wimpy pre-check, no
level/strength restriction — matches this session's cross-lib precedent
that fight is the guarded/safe command and kill is not).
Used admin call dstest->move("/d/budui/bdguangchang1") to place her
with the same 特种兵 NPC (tezhongbing.lpc, combat_exp 30000, vs.
dstest's fresh-character stats) used for the safe fight test in the
original round-one pass, then had dstest issue kill bing from her
own ordinary connection — a real, un-gated fight, full turn-by-turn
combat log, ending in an actual loss:
你两眼一闭,接著屁都看不到了....
你光荣牺牲了。
【马路传闻】某人:死士被特种兵杀死了。
Moved into d/death/gate.lpc (鬼门关) where 白无常
(d/death/npc/wgargoyle.lpc) picked up the standard staged
death_stage() ghost-dialogue sequence (5 stages × 5s, guarded by
death_stage_active per the §7.112 branch audit above) fully
unattended — reconnected afterward and confirmed no stuck state, no
duplicate/orphaned reentry, no debug.log error: dstest had been
correctly reincarnated and moved to /d/taikong/gangkou (太空港口, this
NPC's designated respawn destination), title reset to 老百姓/普通百姓,
HP/food/water all at fresh-respawn values, inventory correctly cleared
of her pre-death items down to just a fresh mailbox (per
wgargoyle.lpc's DROP_CMD->do_drop + new("/clone/misc/mailbox")
logic). log/debug.log gained zero new fatal/error lines across the
entire kill → death → staged ghost dialogue → reincarnate → respawn
pipeline.
dstest is being kept, not cleaned up, as playthrough evidence (same
convention as qxtest/wjtest from the original round-one pass). Save
files: work/data/user/d/dstest.o, work/data/login/d/dstest.o (d/
already existed for prior "d"-prefixed ids in this lib).
本轮修改的文件 / Files modified this round:
libs/xzyx/work/cmds/std/give.lpc(MUDLIB_UID→ROOT_UIDcompile-error fix)
Save files updated/added this round:
libs/xzyx/work/data/user/f/fluffos.o,libs/xzyx/work/data/login/f/fluffos.o(admin's money-clone test props)libs/xzyx/work/data/user/q/qxtest.o,libs/xzyx/work/data/login/q/qxtest.o(money earned + spent, items bought)libs/xzyx/work/data/user/d/dstest.o,libs/xzyx/work/data/login/d/dstest.o(new throwaway death-test character)