info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
笑傲江湖(迷你版)是以金庸小说《笑傲江湖》为背景的武侠 MUD,属于 TMI-2/ES2(Falcon 系)引擎家族,是"笑傲江湖"系列里体积最小、内容最精简的一个版本(作者称之为"mini xo"):地图刻意做得极简,只有扬州城和一座码头小镇两座城市,可加入的门派也只有无量派一家,很适合用来体验这套引擎最原始、最基础的玩法框架;同批的"笑傲江湖最终版"(xo_final)与本档几乎逐文件沿用同一张地图、同一个无量派设定(差异只在少量文件的细节修改),再在此基础上大幅扩充出 10 座城市、16 大门派的更大世界。
English
A wuxia MUD set in Jin Yong's "The Smiling, Proud Wanderer," the smallest, most minimal build in this collection's xo series — the author's own "mini xo." The map is deliberately bare-bones: two cities (Yangzhou and a wharf town) and a single playable sect, the Wuliang (Boundless) Sect, making it a good look at this ES2/"Falcon"-family engine's basic framework stripped of content. Its sibling archive, the Final Edition (xo_final), reuses this same map and sect almost line-for-line (only minor per-file edits differ) while expanding it into a much larger world with 10 cities and 16 sects.
README
内容亮点
- 详见上方简介:极简的双城单派地图与 xo_final 的扩充关系。
在线试玩
https://mudlibs.fluffos.info/xo/
管理员账号 / Admin account
- id:
fluffos - 密码 / password:
Mud@2026 - 中文名 / display name: 浮浮(Fluffos)
- 权限 / level:
(admin)—— 本 lib 的最高巫师权限(通过/secure/etc/wizlist授予,SECURITY_D->get_status()据此判定)。
警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。
本地运行
cd libs/xo
~/src/fluffos/build-debug/src/driver config.fluffos游戏端口:40023。
NOTES · 移植与修复记录
xo — 笑傲江湖迷你版 (The Smiling, Proud Wanderer — Mini Edition)
Archive: xo.zip. Port: 40023. Status: done (boots clean, connects,
plays through login into "create new character?" confirmation with zero
crashes).
What this is
A different, smaller lineage from everything else processed so far in
this batch: secure/daemon/master.c header says "Original from TMI-2 and
ES2, Rewritten by Falcon 96-10-02" — TMI-2 ("The Mud International 2") is
another classic MudOS-era mudlib base, distinct from the "ES II"/nitan
families seen in archives #21-#26. Uses the secure/daemon/{master,
sefun} path convention (not adm/obj/ or adm/single/). Small lib —
1395 .c files, "mini edition" as the name says. No set/query/
delete global simul_efun defined (like rzrmud/xkx2001) — every
object provides its own via inheritance, the architecturally correct
pattern (see AGENTS.md §15).
Fixes applied
1. AGENTS.md §4 (lazy security-daemon load): secure/daemon/
master.lpc's valid_write/valid_read called load_object(SECURITY_D)
unconditionally on every single call (not gated behind find_object()
first), wrapped in catch() but with no re-entrancy guard. Added the
full guard (nosave flag + find_object() check before attempting
load_object()) per the established §4 fix shape, applied proactively
before the first boot attempt given the exact matching pattern.
2. New bug (case-sensitivity, Windows-origin archive on a
case-sensitive Linux filesystem): 3 files (system/feature/char/
command.lpc, cmds/arch/ll.lpc, cmds/arch/localcmds.lpc)
#include <Action.h> (capital A), but the actual file on disk is
include/action.h (lowercase) — silently resolves on Windows'
case-insensitive filesystem, hard-fails here. This was responsible for
the overwhelming majority of the initial lpcc sweep's failures (762
"Undefined class 'Action'" + 155 "Cannot #include Action.h" out of
1395 files, cascading from just those 3 root includes via inheritance)
— fixing the 3 #include lines dropped the failure count from 209 to
72 in one shot (85.0% → 94.8% pass). Checked the whole tree for any
other same-shape case-only filename mismatches (find -iname +
case-insensitive dedup) — none found, this was the only instance.
Interactive test result
Boots clean, connects; welcome message + "last modified 1999.11" credit
line render correctly, empty input at the username prompt correctly
triggers a polite disconnect ("欢迎下次再来" — not a bug), new +
a valid English name reaches the "create new character?" (y/n)
confirmation with zero crashes. Did not create a full character or play
further (out of scope).
lpcc sweep
1395 files, 1323 pass / 72 fail (94.8%, after the Action.h fix). Remaining
72 failures are the usual long tail (a handful of syntax typos in
individual files, a few missing daemons like TASK_D/SendToUser/
SendToMud referenced but not present in this "mini" trimmed-down
archive) — not triaged individually, consistent with AGENTS.md §6b/§13.
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).
2026-07-23: driver rebuild retest + LPC formatter + WASM check
- Formatter: ran
tools/lpc-syntax'sformat-corpus.mjsover all 1395.lpcfiles inwork/; 1363 written, 7 already-conformant, 25 errors (files it refused to touch, expected/fine on legacy code). Spot-checked that this didn't disturb the §4/case-sensitivity fixes above, plus the pre-existing#define private protected/#define nosave nosavecompatibility shim ininclude/globals.h— all intact post-format. - Native retest: rebuilt
~/src/fluffos/build-debug/src/driverbooted clean (zero fatal errors inlog/debug.log— the two "mudlib error handler"/#define __DEFAULT_PRAGMAS__lines are the driver's own startup config dump, not errors). Went further than the previous pass (which had stopped at the "create new character?" confirmation) into a full end-to-end registration + play session: real Chinese name 秦风丁/秦风戊, English id/confirm/Chinese name/password/email/gender all completed, dropped into 小秦淮客寓;lookshowed the correct room+NPCs,scoreproduced a correct full character sheet,quitcorrectly enforced the "must play 30 real minutes before saving" gate and disconnected cleanly on confirmingy. Zero realdebug.logerrors. - WASM: booted cleanly (only the expected non-fatal
socket_create/socket_bind/socket_connect"Undefined function" compile errors fromsystem/std/net/client.lpc, since thesocketspackage isn't built into this WASM binary — matches the documented non-fatal WASM restriction). Registration itself proceeds correctly all the way through the gender prompt (m/f) — but reproducibly, across several--idle/--timeoutvalues (1.0/2.0/3.0/6.0s), the transition into the live game world (enter_world()) never completes: no banner/room text appears after answering the gender prompt, and subsequentlook/quitinput gets the driver's generic "什么? 你想干嘛?" (unrecognized command) fallback instead of real output. This is not the documentedquery_ip_number()limitation (this lib never gates login on IP format). It also does not reproduce on the native rebuilt driver (full playthrough above was clean), and notably does not reproduce onxo_final— a very close sibling with near-identicallogind.lpcregistration/enter_world()code — under the exact same WASM harness (seexo_final's own NOTES.md entry, verified working end-to-end). Root cause not identified (the WASM harness's debug-log-open failure at boot, a separate pre-existing cosmetic warning, means any real runtime error thrown duringenter_world()here would be silently discarded rather than surfaced anywhere inspectable). Verdict: flagged as a possible WASM-specific gap isolated to this lib's own code path, not patched — native play is completely unaffected, and chasing it further didn't seem proportionate to the smoke-test scope of this pass. Worth a closer look in a future WASM-focused pass.
2026-07-23 (integrity review): WASM world-entry hang RESOLVED — was the harness, not the mudlib
Re-ran the full WASM registration flow (new → id → confirm → Chinese name
→ password ×2 → email → gender) against the same build-wasm binary but
with the FIXED scripts/wasm_client.js (the copyDir() log-directory
recursion fix landed in the final commit of the previous pass, AFTER this
lib's WASM test had been run). Result: enter_world() now completes
normally under WASM — MOTD banner, 小秦淮客寓 start room, look, and
the quit save-gate prompt all appear exactly as in the native run. No
mudlib race exists in xo's enter_world path; the earlier "reproducible
world-entry hang" was the old harness failing to recreate the lib's
nested log/ subdirectory shape in the WASM in-memory FS (this lib's
log/ has 6 nested subdirs — acct/catch/log/room_log/runtime/static),
so an early uncaught write_file()/log_file() during enter_world threw
ENOENT and silently aborted the flow — precisely the harness gap class
described in that commit's message. Verdict: fully playable under
WASM; the previous NOTES entry's "possible WASM-specific gap isolated
to this lib" flag is closed.
Also noted (pre-existing, original-author code, left as-is): system/
daemon/logind.lpc's enter_world() contains two leftover debug
printf("beforee exec...") / printf("before setup...after exec..")
lines that print to every player at world entry — present since the raw
archive (verified in the initial conversion commit), cosmetic only.
WASM-enablement pass (loopback-allow / gate bypass / admin seed)
Standard WASM-first pass per AGENTS.md §1.3b/e and §1.5. Gates patched:
system/daemon/band.lpcis_banned()(~line 39) — loopback / empty / malformed-IP short-circuitreturn 0;at the top (inline test, no helper needed — only one gate function in this daemon).system/daemon/logind.lpcCheckDupIp()(~line 148) — multi-login deny list now exempts loopback/malformed-IP connections (return 0;before the multi_deny regexp loop).logon()'sLOGIN_DELAYstartup-grace gate (~line 102) is compiled out (LOGIN_DELAY not defined anywhere) — left as-is, noted only.uptime() < 10inlogon()(~line 125) is cosmetic (banner text choice), not a gate — left intact.
Admin account seeded: id fluffos, pw Mud@2026, name 浮浮, granted
(admin) via fluffos (admin) appended to secure/etc/wizlist.
Verified: real registration (ENTER/new/fluffos/y/浮浮/pw×2/email/m →
landed in 小秦淮客寓), then relogin as fluffos →
update /system/daemon/logind → 成功, score correct. Retest: fresh
normal registration (秦风, f) end-to-end with look/score correct (quit
shows the original 30-min new-account retention prompt — content timer,
kept per policy); test char save removed; zero new debug.log errors.
Save file: work/data/user/f/fluffos.o (NOT gitignored — normal add,
no force-add needed).
Fail-closed retrofit for the loopback-allow gate (2026-07-24)
The loopback helper above was originally written matching the
project-wide convention at patch time (AGENTS.md §1.3b), which also
treated an empty/non-string/malformed query_ip_number() result as
loopback, defensively, because the WASM driver used to return garbage
there. That underlying driver bug is now fixed (fluffos commits
e33bb5da "fix: query_ip_number() returned uninitialized garbage under
WASM" and 007bb863 "feat: synthetic resolve() on WASM instead of
raising an LPC error", both 2026-07-23; the locally-built
build-debug/build-wasm binaries already postdate both commits), so
treating unparseable IPs as trusted is a fail-open gap with no remaining
justification. Retrofitted to fail-closed: loopback is now strictly
ip == "127.0.0.1" || ip == "::1" || ip[0..3] == "127." (with a
stringp() guard before the slice) — a malformed/empty IP now falls
through to the NORMAL gate instead of being treated as local. Retested
after tightening: fresh driver boot clean, fluffos loopback login and
its wizard update command both still work; zero new debug.log errors.
深度功能测试 / Deep functional test (2026-07-24)
First real *playthrough* pass on this lib (all prior passes verified
only registration + look/score/quit + admin login). This "mini"
archive has no help newbie/help intro file at all (help/user/
contains only a single sect help page and no topics index — a genuine
content gap in this trimmed archive, not a conversion bug; help with
no argument literally prints 0 to the player, see Bug 8 below), so the
test path was derived entirely from reading room/NPC source: register →
小秦淮客寓 (start room, Yangzhou) → walk to 崇雅书院/至止堂 and learn
literate from the teacher NPC 增城湛 via qingjiao → (admin-assisted,
see below) reach 无量剑派东宗's hall and join via apprentice/kneel
→ a real fight → a real death → the death-realm/reincarnation flow → a
shop purchase → quit/reconnect testing. Found and fixed eight
distinct programming bugs (compile errors, a driver-API-misuse crash, and
a silent-stranding move() bug), one of which is a well-established
project bug class (§7.25) and most of the rest are one-off typos of a
kind AGENTS.md already tracks (§6.6/§8.5-adjacent); also captured a
driver-level SEGFAULT, corroborating the §10.8 "ambient background
processing can crash the whole process, invisible to debug.log" class
with a genuinely different C++-level mechanism (a dangling shadowed
object pointer walked during the periodic reset() sweep) than either
of the two prior occurrences.
Note on this pass's scope: partway through this session the orchestrating session clarified that only genuine *programming* bugs are in scope for live fixes (compile errors, driver-API misuse, missing null/objectp checks around calls that can crash, obviously-wrong references) — game-balance/content/design questions are explicitly OUT of scope, even when they look surprising. One thing found live (a "safe" sect mirror-spar that turned out to deal lethal, real damage — see "Observed, not fixed" below) falls squarely in that excluded bucket and was deliberately left untouched, documented only.
Wuliang sect is not reachable by ordinary walking in this archive:
d/menpai/wuliang's only outbound connection to the rest of the map
(shanjiao.lpc's northwest exit) points at /d/map/xinan/jiangbian,
and /d/map/ doesn't exist anywhere in this "mini" archive (confirmed:
d/map is entirely absent). No city room links into
d/menpai/wuliang either. This means the sect content described in the
lib's own README ("目前只有扬州城和无量派两大门派") is real and
functional but currently has no in-game path to it at all — every
sect-related test below (apprentice/kneel, the mirror-spar,
qingjiao) was reached via admin goto/summon, not by walking. This
looks like a genuine map-connectivity gap from the archive trim (not
something we fixed — no defensible "correct" reconnection point exists,
and fabricating one would be a content decision) but is worth flagging
prominently since it's a bigger blocker to real play than any single bug
below.
Test characters (kept as evidence, not cleaned up):
qinfengding/ 秦风丁 (male, pwAa123456) — first registration, used for the teacher-NPCqingjiaotest and a full cleanquit(both the "too new to save" no-save-confirm path AND, much later in the same real session once 30 real minutes had elapsed, a REAL save-and-quit, reconnect-verified). Currently in小秦淮客寓wearing 青布衣衫, literate skill improved once via 增城湛.qinfengwu/ 秦风戊 (female, pwAa123456) — used for the prompt net-dead/reconnect test and the shop-purchase test (bought 白缎衫 from 沈万福 inbaiyi_dianfor 800 铜钱, funded via an admin-dropped/ player-picked-up 银子 since fresh characters start with no money). Currently in沈家白衣铺, holds 白缎衫 + 200 铜钱 + starting gear.qinfenglong/ 秦风龙 (male, pwAa123456) — used for the sect-join (apprentice zuo/kneel), the mirror-spar-that-wasn't-safe (see below, died to 老高), and the death/reincarnation flow. Deliberately has no save file — during testing this character hitquit+ywhile still under the lib's real 30-real-minute-before-first-save gate (cmds/comm/quit.lpc'sconfirm_quit_with_nosave()), which correctly and intentionallyrm()s both thelogin/anduser/save files — confirmed this is the INTENDED behavior (matches the on-screen warning verbatim), not a bug; documented here only so a future pass isn't confused by the missing.ofile for an id that clearly saw a lot of activity indebug.log-adjacent logs (data/log/q/qinfenglongstill exists and shows the session).- Admin:
fluffos(pre-existing, pwMud@2026) — used throughout forgoto/summon/force/update/callto reach the disconnected sect zone and to recompile fixes live.
Verified working
- Registration end-to-end with real Chinese names (秦风丁/秦风戊/秦风龙), landing in
小秦淮客寓with correctlook/score/i. - Organic teacher-NPC skill learning:
qingjiao zeng literateagainst 增城湛 (崇雅书院/至止堂) — first attempt succeeds ("你听了增城湛关于 读书识字的讲解阐释..."), immediate repeat correctly refused ("贪多不化 ..."). - Sect join (
apprentice <NPC>→ NPC leads you to a side hall →kneelonce the NPC's own delayed dialogue sets the flag) against 左子穆, leader of 无量剑派东宗 — full flow completed, disciple rank/family granted, sword received, persisted correctly across an unrelated driver restart (see Bug 3's segfault below — after the driver came back up,qinfenglong's family/rank data was intact even though their physical location reset to the last realstartroom, which is correct/expected since location is separate save state from family). - A real fight to the death (see "Observed, not fixed" — the sect's mirror-spar
accept_fightbranch actually killed a fresh, unarmed disciple in one hit), the full death → 黄泉路 → 鬼门关 → 酆都地府 → 阎罗大殿 flow, and (after Bug 7's fix) the reincarnation NPC 判官 (chacha.lpc) correctly walking through its dialogue and moving a ghost with an empty inventory back to a real, live room. - A real shop purchase:
list shen(vendor goods listing) thenbuy baiduan shan from shen— correct price/change arithmetic, item added to inventory, auto-save fired, zero crashes. quit: both the "too new, confirm without saving" path (explicitly wipes save files — confirmed intentional, seeqinfenglongabove) and, later in the same real session once past the 30-real-minute mark, a genuine save-and-quit → reconnect round trip with correct location/inventory/score restored.- A prompt (well within any timeout) unclean net-dead disconnect + reconnect (
qinfengwu, and incidentallyqinfengding/qinfenglongacross nearly every test in this pass, sincemudclient.pyclosing its socket without sendingquitIS an unclean disconnect) — this lib's ownnet_dead()/reconnect()(clone/user/user.lpc) never relocates the player at all (noVOID_OBpark, no location temp var), so there is no §7.20-style stale-location-on-reconnect risk to find here; reconnecting mid-session always resumed exactly in place, every time. debug.loggrepped after everyquit/crash/compile-fix in this session, per the AGENTS.md §10.7 mandate — see the segfault entry below for why this matters: at NO point diddebug.loggrow by even one line beyond its pre-session baseline (219 lines, unchanged for the entire ~30-minute session), despite multiple live compile errors, one live driver-API-misuse crash, and one full driver segfault all happening during that same window. Every one of those was caught purely by watching the client transcript / driver stdout / the in-liblog/runtimefile, neverdebug.logitself.
Not verified live (explicitly)
- The full 900-second (
NET_DEAD_TIMEOUT) unclean-disconnect wait: not performed, for time-budget reasons. Mitigating factor found by code reading instead: this lib'snet_dead()(clone/user/user.lpc) never moves the player toVOID_OBor any holding room at all — it just stops the heartbeat and schedulesuser_dump(DUMP_NET_DEAD)after the timeout, which (per the same file) simply calls the ordinarycommand("quit")at the player's CURRENT, never-changed location. Both of the two independent root causes AGENTS.md §7.20 documents (void-parking without restore, and areconnect()that never gets called) require the net-dead path to relocate the player in the first place — this lib's simpler design structurally can't hit either. Lower-priority to chase further given that structural argument, but flagged honestly as code-review-only, not live-tested. - A wizard
check_rein/death_stagerace was observed where re-entering阎罗大殿multiple times (to re-trigger 判官's dialogue during iterative testing) stacks multiple concurrentcall_outchains with no dedup guard (init()callscall_out("check_rein", 2, ob)unconditionally on every room entry) — plausible under real multi- minute AFK/re-entry play, not just repeated admin testing, but was not cleanly isolated/reproduced as a standalone bug this pass (my own repeatedgoto/summonre-entries are a confound); flagged as worth a closer look in a future pass rather than fixed blind.
Bugs found and fixed
1. Unterminated string literal (×3, same shape, different files) —
AGENTS.md §6.6-adjacent (pre-existing authors' typo, not a new bug
class): a Chinese-text string literal missing its closing "
before the trailing comma, causing the driver to keep consuming
subsequent lines as string content until it hits the next "
(usually inside a //-commented line, since the comment marker means
nothing once already inside an unterminated string) and then throwing
a cascade of "Illegal character" / UTF-8-mid-codepoint errors once the
accidental early-close lands mid-multibyte-character.
- d/menpai/wuliang/npc/zuo.lpc:69 — this one is the single most
impactful fix in this pass: 左子穆, the sect's own leader/master,
failed to compile entirely, so d/menpai/wuliang/dating.lpc's room
population silently dropped him (caught by std/room.lpc's already-
catch()-guarded make_inventory() — this lib is NOT vulnerable
to the unguarded §7.25 crash shape, just the graceful-degradation
side of it) — meaning the ENTIRE sect-join mechanism was inert
(no master NPC to apprentice) until this fix.
``lpc
// BEFORE:
"姓名" : "嗯,你既知我姓左,怎会不知在下便是无量东宗掌门人左子穆?,
// AFTER:
"姓名" : "嗯,你既知我姓左,怎会不知在下便是无量东宗掌门人左子穆?",
`
- system/skill/misc/yuanyang-dao.lpc:33 (the "鸳鸯刀法" weapon
skill's 4th combat move) — same shape, fixed identically.
- system/skill/misc/taizu-quan.lpc:181` (the "太祖长拳" unarmed skill's
"英雄独立" move) — same shape, fixed identically.
2. Undefined-macro inherit (×2 files): d/city/yangzhou/waifang.lpc
and d/city/yangzhou/woshi.lpc (both real, reachable rooms — a
courtesan-house's outer/inner room, linked from meixiang_yuan.lpc)
did inherit DOOR_ROOM; — DOOR_ROOM is never #defined anywhere in
this archive (no door_room.lpc base class exists at all), a hard
compile error (expecting L_STRING or '('). Every other room in this
lib that needs a door (e.g. d/menpai/wuliang/damen.lpc) just
inherits plain ROOM and calls create_door(), which std/room.lpc
already provides directly — DOOR_ROOM was never real content, just
a stale reference. Fix: inherit ROOM; in both files.
3. Malformed function declaration swallowed into a comment:
system/skill/basic/kongshou.lpc:37-38 — the base "unarmed combat"
skill, needed on literally every unarmed combat round for every
character. The Chinese explanatory comment and the following
function signature were on the same physical line with no separating
newline, so the ENTIRE function header got absorbed into the //
comment, leaving a bare orphaned { on the next line
(syntax error, unexpected '{'). Reproduced live: fighting as an
unarmed disciple spammed a "Compiling error .../kongshou.lpc ... *No
program in object" message to the player on every single combat
round (both attack and parry attempts), since skill.lpc's combat
dispatch tries to load this file fresh every time it's referenced and
it never successfully compiles.
``lpc
// BEFORE:
// 这个函数用来区别这种天生的技能与其他后天学习的技能int is_native_skill()
{
return 1;
}
// AFTER:
// 这个函数用来区别这种天生的技能与其他后天学习的技能
int is_native_skill()
{
return 1;
}
`
Checked the other 4 sibling files in system/skill/basic/ with the
same is_native_skill() pattern (wuqi.lpc, horsedodge.lpc,
dodge.lpc, yeshou.lpc`) — all correctly formatted, this was an
isolated one-off typo, not a copy-pasted class.
4. Missing #include <armor.h> (×2 files) — AGENTS.md §6.1:
d/city/yangzhou/npc/cloth/cloth.lpc (the base clothing template) and
d/menpai/wuliang/npc/obj/choushan.lpc (a sect disciple's robe, worn
by the live npc/qyz.lpc... which itself turns out to be dead/
commented-out content, see below — fixed anyway since it's a one-line,
zero-risk fix and the exact §6.1 shape) both did inherit CLOTH;
without #include <armor.h> (where CLOTH is #defined). Every
sibling cloth file in the same directory has the include; these two
were just missing it. Fix: add #include <armor.h> above the
inherit.
- cloth.lpc also had a second, independent bug on the same pass:
set("value",); — a call with a dangling comma and no second
argument (Wrong number of arguments to 'set', expected: 2, got:
1). Every sibling cloth file's equivalent line reads
set("value", 800)-shaped; fixed to set("value", 0) (a sensible
zero default for what is explicitly a base/template object, per its
own empty set_name("", ...) treatment elsewhere in the same
create()).
5. Driver-API misuse: missing objectp() guard after a move() call
that can legitimately self-destruct its argument — matches AGENTS.md
§7's "missing objectp()/stringp() checks" class, closest existing
relative is §7.25's shape (a call that can legitimately fail/vanish,
with no guard on the caller side). cmds/verb/drop.lpc:57's
do_drop() calls obj->move(environment(me)), checks only the
integer return value, then unconditionally calls further methods
(obj->is_character(), obj->query("unit"), obj->value()) on the
same obj reference. d/menpai/wuliang/npc/obj/sword.lpc's own
move() override (a soulbound-weapon "剑在人在,剑亡人亡" mechanic)
legitimately destruct(this_object())s itself and returns 1
(success) when dropped outside a valid ownership context — a fully
intentional, working design (see sword.lpc:33-52), but do_drop()
has no way to know that and dereferences the now-destructed obj
immediately after. Reproduced live: drop sword (as a disciple
standing in the death realm, where the sword's ownership check fails)
printed the correct in-fiction "剑转眼间断成了数块,不见了。" message,
immediately followed by an uncaught *Bad argument 1 to EFUN
call_other() Expected: object, string, array, Got: int(0) runtime
error (visible in log/runtime), aborting the rest of do_drop()
mid-function.
``lpc
// BEFORE:
if (obj->move(environment(me))) {
if (obj->is_character())
// AFTER:
if (obj->move(environment(me))) {
// obj->move() can legitimately destruct obj as a side effect (e.g.
// a bound/soulbound weapon shattering when dropped outside its
// valid owner context -- see d/menpai/wuliang/npc/obj/sword.lpc's
// own move() override) -- guard before touching it further.
if (!objectp(obj)) return 1;
if (obj->is_character())
`
This is a general, call-site-independent fix (guards the ONE shared
do_drop() used by every drop invocation, including the amount-
split and drop all` paths), not specific to the sword.
6. Silent-stranding move() to nonexistent content in the death/
reincarnation flow — same shape as AGENTS.md §7.18 (hardcoded path
into content missing from THIS archive), new file/lineage instance:
d/place/death/npc/chacha.lpc's death_stage() — the 判官 NPC that
finalizes reincarnation — picks a random(3) destination for a newly
-reincarnated ghost. Only branch case 0
(/d/city/yangzhou/kuixing_ge) resolves to real content in this
trimmed archive; case 1 (/d/map/zhongyuan/nanmen — /d/map/
doesn't exist anywhere in this archive) and case 2
(/d/city/lanzhou/guangchang — lanzhou doesn't exist either) both
silently fail. Confirmed the failure mode live (via goto on the
admin account, which has its own explicit existence check and
reported "没有这个玩家、生物、或地方" without moving): move()'s own
implementation (system/feature/base/move.lpc:74-80) already
gracefully notify_fail()s rather than crashing for a target that
doesn't exist at all (as opposed to one that exists but fails to
compile, which throws) — but chacha.lpc never checks move()'s
return value, and notify_fail() from a call_out-driven context
with no active command dispatch never surfaces to anyone. Net effect:
2 out of 3 times, a reincarnating ghost's ghost flag gets cleared
(reincarnate() already ran) but they're never actually relocated —
permanently stuck in 阎罗大殿, a death-realm-only room with (per
鬼门关's own room text) no way back to the living world through
ordinary movement. Also checked the "西域"/gaochang special-case
branch one line above — /d/city/gaochang/center doesn't exist
either, but confirmed (via logind.lpc's own start_rooms array,
where the gaochang entry is commented out) that no character in
this archive can ever actually be tagged hydra/desert/from=="西域"
in the first place, so that branch is already-dead and left alone.
``lpc
// BEFORE:
switch (random(3)) {
case 0: ob->move("/d/city/yangzhou/kuixing_ge"); break;
case 1: ob->move("/d/map/zhongyuan/nanmen"); break;
case 2: ob->move("/d/city/lanzhou/guangchang"); break;
}
// AFTER: (both dead branches repointed to the one confirmed-live
// destination already used by case 0, matching AGENTS.md #7.18's
// fix pattern -- see the file for the explanatory comments kept in
// place)
switch (random(3)) {
case 0: ob->move("/d/city/yangzhou/kuixing_ge"); break;
case 1: ob->move("/d/city/yangzhou/kuixing_ge"); break; // was the dead /d/map/ path
case 2: ob->move("/d/city/yangzhou/kuixing_ge"); break; // was the dead lanzhou path
}
`
Verified live end-to-end after the fix: dropped all items (a
prerequisite the same NPC enforces earlier in its dialogue), re-
entered 阎罗大殿, sat through 判官's full multi-stage dialogue, and
was moved to 小秦淮酒楼` (a real, live room) successfully.
7. Operator-precedence + typo bug, NOT observed live (dead code given
current data, fixed proactively since it's a trivial and clearly
unintentional pair of mistakes): cmds/skill/study.lpc:127-128 —
if (bonus = book["bonus_jibie"] > 0) me->improvve_jibie(...). Two
independent bugs stacked: = binds looser than > in this grammar,
so bonus was being assigned the BOOLEAN result of the comparison
(0 or 1) rather than the actual configured bonus amount (contrast
with the parallel bonus_jilei branch a few lines up, which correctly
does bonus = book["bonus_jilei"] then checks it); and
improvve_jibie (double-v) is a typo for the real function
improve_jibie (defined in system/feature/char/skill.lpc:351, used
correctly by name everywhere else including 3 lines below in the same
function's else branch) — an Undefined function error waiting to
happen the moment it's ever reached via ->. Not reachable with
current data: grepped every book/skill data file in this archive
and none of them ever set "bonus_jibie" to a positive value, so
book["bonus_jibie"] > 0 is always false and this exact branch never
executes today — but the fix is one-line-obvious and harmless, so
applied proactively rather than left as a landmine for the first book
that ever sets that key.
``lpc
// BEFORE:
if (bonus = book["bonus_jibie"] > 0)
me->improvve_jibie(book["name"], bonus);
// AFTER:
if ((bonus = book["bonus_jibie"]) > 0)
me->improve_jibie(book["name"], bonus);
``
8. Cosmetic, not fixed (too minor/ambiguous to count as a real
programming bug, documented only): cmds/comm/help.lpc's main()
does cat(HELP_DIR + "topics") when called with no argument;
help/user/topics doesn't exist anywhere in this trimmed archive
(genuine content gap, not a conversion bug). secure/sefun/file.lpc's
cat() is write(read_file(file)); read_file() of a missing file
returns int 0, and write() coerces that to the literal string
"0" — so a bare help with no topic just prints 0 to the player
instead of a message like "没有说明文件". Left as-is per the "don't
fabricate missing content" policy (the fix would require deciding
what a proper topics index should say, a content question) — but
flagged here in case a future content pass wants to add a real
topics file, at which point this stops mattering entirely.
Observed, not fixed (design/content, out of scope per this pass's corrected instructions)
- The sect's "mirror match" isn't actually safe:
d/menpai/wuliang/ npc/laogao.lpc'saccept_fight()has a friendly-dialogue branch for attackers whosefamily/family_namematches the sect ("好吧,我就陪你 练几招吧,看好了哦。") that reads exactly like the "safe sparring mechanism" AGENTS.md §10.7's checklist asks testers to find and use before risking a real fight — but the branch doesn't cap damage, disable death, or use any different combat resolution than a genuine fight; it's real combat with friendlier flavor text only. Used it as directed by the checklist (attacker was a same-sect disciple,qinfenglong) and it killed a fresh, unarmed, zero-combat_expcharacter in a single hit (老高 immediately wielded his real sword and landed a killing blow: "你没能躲开,只听见你一声惨嚎,悬泉剑已在你右肩 划出一道深可及骨的可怕伤口!!" → death). This is internally consistent (the code does exactly what it's written to do, consistently) and matches the exact "a 'safe' fight sparring mechanic that isn't perfectly safe" example the orchestrating session explicitly called out as NOT in scope — documented, not touched. - A ghost can leave the death realm without ever reincarnating: while chasing Bug 6 above,
qinfenglong(still flaggedghost, in阎罗大殿) got picked up by an unrelated, already-existing safety net —system/feature/user/alias.lpc'sprocess_input()checks!environment(this_object())on every keystroke and teleports a player with no environment intoVOID_OB(clone/misc/void.lpc, "天涯海角,梦的尽头", with a workingoutexit to a real room). The room the character had been standing in was most likely reaped by this archive's ordinary idle-object cleanup during an unrelated multi- minute admin digression, not anything wrong with the death-realm code itself — the safety net caught it and worked exactly as designed (a live, escapable room, not a dead end). Net observable effect: the character ended up back in the living city, walking around, while still internally flagged as aghost(never went throughchacha.lpcat all this time) — an odd-looking but non-crashing state that self- resolved the next time阎罗大殿was re-visited and the reincarnation dialogue actually completed. Not chased further (unclear whether this is "a bug" or just an unusual but harmless interaction between two independently-correct systems); documented for anyone who sees a【 鬼 魂 】player wandering a normal city room and wonders why.
Driver segfault (corroborates AGENTS.md §10.8, new immediate mechanism)
~26 minutes into this session, during ordinary ambient play (not
triggered by a specific command — the crashing call stack is entirely
inside the driver's own periodic reset() sweep, backend.cc's
look_for_objects_to_swap()), the native driver process died outright
with a SIGSEGV. debug.log showed absolutely nothing — identical to
both prior §10.8 occurrences (xjcq2000, shiji), reinforcing
that this class of failure is genuinely undetectable by log-watching
alone; only the redirected driver stdout (captured per the standing
recommendation from that section) had anything.
Captured backtrace (driver build fluffos-20260721-25c87bbc):
backend_run_one_gametick -> look_for_objects_to_swap -> reset_object
-> safe_apply(APPLY_RESET) -> apply -> apply_low -> eval_instruction
-> f__call_other -> apply -> apply_low [SIGSEGV]
src/vm/internal/apply.cc:201, in apply_low:
while (ob->shadowed && ob->shadowed != current_object &&
(!(ob->shadowed->flags & O_DESTRUCTED))) { // <- crash hereThis is a different immediate C++-level mechanism than either prior
occurrence (both of those were FATAL: Object ... ref count 0, but not
destructed internal-consistency aborts from free_svalue(); this one
is a raw segfault dereferencing ob->shadowed, apparently a dangling
pointer, while a reset()-triggered call_other() walks the shadow
chain) — but the same broad category (driver-level object-lifecycle
memory corruption surfacing later, during unrelated background
activity, as a process-ending crash). Not mudlib-fixable; not root-
caused to a specific LPC source pattern (the corruption, whatever it
was, had already happened before this crash — the reset cycle just
happened to be the next code to touch the bad pointer). Driver was
restarted (fresh PID, confirmed via readlink -f /proc/<pid>/cwd
before doing anything with it) and testing continued; no second
occurrence in the remaining ~30 minutes of this session. This is now
the third independent occurrence of "background driver processing
crashes the whole process, invisible to debug.log" across three
unrelated libs/lineages — per §10.8's own escalation note, worth
promoting to a driver-level (~/src/fluffos) investigation rather than
continuing to treat each new occurrence as a per-lib mudlib finding, if
this keeps recurring.
lpcc sweep
Baseline (start of this pass) 1323/1395 pass (94.8%). After this pass's
fixes: 1331/1395 pass (95.4%). Remaining 64 failures are the
already-documented long tail: genuinely corrupted/non-LPC content under
d/menpai/wuliang/east/ (plain-text poem fragments, garbled binary, a
"By XO team... since 1997 April." credits blob — not LPC source at all,
pre-existing archive corruption, not a conversion bug, and this whole
subtree turns out to be unreachable anyway per the map-connectivity gap
noted above), missing daemons (TASK_D, BET_D, SendToUser, NBUG)
consistent with this "mini" archive's documented trimming, and a handful
of dead/superseded duplicate files (system/menpai/wuliang/zuo_zimu.lpc
etc. — confirmed via grep to be shadowed by a live npc/-subdirectory
version and never referenced by any room's objects mapping, left
alone per the project's "leave dead code alone" convention) — not
triaged further as none are live/reachable.
WASM 修复摘要(迁移自 meta.json 的 group_note)
笑傲江湖 XO/TMI-2/ES2/Falcon 基础版(迷你版)。状态已从过时的 limited 修正——这份档案自己的 README 和 group_note 里从未记录过任何缺陷说明,本轮重新测试也没有发现:这份压缩包没有随附管理员存档(只有一条 wizlist 阶层授权)——已改为用一次全新的 'new' 注册(fluffos/Mud@2026)来验证,干净地进入起始区域(小秦淮客寓),并以正常的告别信息 quit。
§7.86 跨库扫描修复(留言板 post 崩溃)
BULLETIN_BOARDinherit+ 多余replace_program()致命形状(AGENTS.md §7.86,post命令崩溃):全档案 4 处命中,已删除多余的replace_program(...)调用(保留inherit),逐文件保留原有行尾格式(CRLF/LF 按文件原样)。本次为跨库 §7.86 扫描修复(触发原因:该 bug 已在 6+ 个互不相关的血统家族独立确认,属于近乎普遍的拷贝粘贴模式),仅做编译检查(驱动干净启动、端口正常监听),未做完整 §10.7 深度游玩测试。
深度功能测试第二轮 / Deep functional test round two (2026-08-15, post driver-upgrade re-test)
驱动于 2026-08-12 升级后的重测。标准检查清单发现并修复四处问题:
1. cmds/app/update.lpc(AGENTS.md §7.106):完全没有
environment(me) 空值防护(if (obj = present(file,
environment(me)))),补上
if (environment(me) && (obj = present(file, environment(me))))。
2. secure/sefun/file.lpc:log_file() 没有 assure_file()
目录预建保护,补上调用及前向声明;cat() 补上
read_file() || "" 空值防护。
3. secure/daemon/master.lpc::log_error()(AGENTS.md §7.10 大小写
坑的又一实例,与本轮在 xlqy_new2007 上发现的一样):
strsrch(message, "warning: ")(小写、带尾随空格)逐字节对不上
本驱动实际吐出的大写 Warning: ,等于完全没有过滤——本档案这处
还额外没有 wizardp() 分流(对所有连线玩家一视同仁广播),改成
不含开头 w/W 的 "arning:" 子串匹配(§7.10 标准写法)后即可正常
过滤警告,未额外新增巫师分流(不在本轮范围内,且原代码本就没
有这层区分)。
4. clone/user/user.lpc、clone/user/wizard.lpc 的 reconnect()
(AGENTS.md §7.108,第十六条独立确认的血统):两个档案各自独
立定义 reconnect()(wizard.lpc 覆写而非继承 user.lpc),均
缺少 enable_commands()。system/daemon/logind.lpc 有同款
exec(old_link, user); 踢掉重复登录写法。按 §7.108 记录的写法
预防性修复两处,现场用两个真实连线复现"保持第一个连线不断开→
第二个连线登录→答 y 踢掉旧连线"验证:score 修复后立即正常显
示完整角色档案。
现场验证摘要
驱动干净启动,管理员 fluffos/Mud@2026 登录(回车进入→id+密码)
成功进入游戏世界,update /system/daemon/logind 成功验证真实写入
权限,现场未观察到编译警告泄漏(确认 log_error 修复生效)。踢掉重
复登录重连路径现场验证通过(见上)。debug.log 全程干净(216 行,
无真实错误)。
本轮修改的文件
work/cmds/app/update.lpcwork/secure/sefun/file.lpcwork/secure/daemon/master.lpcwork/clone/user/user.lpcwork/clone/user/wizard.lpc
§7.100 sub-threshold instance (2026-08-20)
Found during the §7.100 tail-sweep (below the original 166-lib survey's
=100-occurrence threshold, never checked). 73 live
replace_program(ROOM); occurrences across 73 room files — mostly a
large d/menpai/wuliang/*.lpc sect-zone cluster (68 rooms including a
west/ subdirectory), plus d/city/matou/mache.lpc/kechuan.lpc and
a d/place/death/*.lpc cluster of 8 rooms. No room-building tool
exists in this lib. 4 pre-existing already-//-commented instances
left untouched. Fixed by deleting the redundant lines. Verified via a
clean native driver boot (zero new debug.log errors, port listening,
killed by exact PID after ~8s).
深度功能测试第三轮 / Deep functional test round three (2026-09-03)
新角度:巡捕游荡触发的城门 reset/make_inventory 路径(log/catch
里成串的 *Bad argument 1 to EFUN call_other() ... Got: int(0))、
留言板 post/read、酒楼 list/buy、真实死亡进入地府。
Bug(AGENTS.md §7.73 新实例):迷你版把装备挪到 npc/obj/,
NPC 仍按全局 HEAD_DIR/BLADE_DIR 取值 → 每次城门 reset 都
call_other(0)
xunbu 的 random_move() 懒加载城门房间时,make_inventory 克隆
士兵/卖花姑娘,其 create() 里无防护的 carry_object(...)->wear()/
wield() 对缺失路径返回 0,立刻炸:
| NPC | 坏路径 | 本档案实际位置 |
|---|---|---|
| liu_yan / run_yu | HEAD_DIR "huang_m" / "yu_jin" 等花 | d/city/yangzhou/npc/obj/*.lpc |
| shibing1 / shibing2 / xiaowei | BLADE_DIR + "changdao" | 同上 obj/changdao.lpc |
xo_final/xajh2 在全局 clone/wear/head/、clone/weapon/blade/
里有这些文件,所以同名代码在兄弟档不炸——这是迷你版裁剪后的路径
错位,不是内容彻底丢失。vendor_goods 也指向同样的坏 HEAD_DIR
路径,卖花 list/buy 同样会失败。
修复:花与长刀改为 __DIR__ "obj/...",并对所有
carry_object→wear/wield 链加上 §7.73 标准守卫(先赋值再
if (ob))。现场验证:goto 通泗门/安定门/镇淮门/草河小街/
禾嘉街,士兵与柳烟均正常出现;list liu yan 列出六种花;
buy 干菜包子 from xiao er(酒楼)成交;游荡约 20s 后
log/catch 中 0 条 call_other 错误(仅剩启动时已知的
emoted 损坏存档 restore_object 警告,CATCH 住、与本轮无关)。
本轮其它现场验证(无新 bug)
- 注册(字母-only id,3–12)→ 小秦淮客寓;管理员
fluffos/Mud@2026 - 留言板:
post <标题>→ 正文 →.→read N正常(§7.114 形状的edit/input_to通路干净) - §7.111
trace_line已有obj ? file_name : "<none>"守卫 - §7.112
chacha/mengpo的death_stage_active守卫在位; §7.113reconnect()含enable_commands()+set_heart_beat(1) - 死亡:
call <mortal>->die()进入黄泉路,北行经孟婆至鬼门关; 判官转世目标此前已按 §7.18 修过(三支均指向现存的kuixing_ge) give对 NPC 的obj->value()→destruct分支与兄弟档同形,是 给 NPC 钱的惯用写法,不是 §7.201(那是给玩家也 destruct)
本轮修改的文件
work/d/city/yangzhou/npc/liu_yan.lpcwork/d/city/yangzhou/npc/run_yu.lpcwork/d/city/yangzhou/npc/shibing1.lpcwork/d/city/yangzhou/npc/shibing2.lpcwork/d/city/yangzhou/npc/xiaowei.lpc