Storm: Rising Tempest

✅ 可玩

风云之风起云涌

fyzfqyy

🔑 fluffos / Mud@2026 更新 66a3bd8 2026-10-28 源码 下载 ZIP

▶ 开始游玩 · Play Now

一个以古龙小说为背景的"风云"MUD。这份档案的实际游戏地图相当单薄:全库只有约 48 个带房间描述的文件,且大多数分散在各个巫师的个人目录下,而不是一套完整的官方城镇/门派地图;唯一较为完整的官方场景是 `quest/kaifeng/` 的开封"衙门",包拯、展昭都驻扎在此。注册流程把管理密码与登录密码彻底分离,比常见的单密码注册更谨慎。

English

A Gu Long-themed “Storm” (风云) MUD whose actual built world is thin: only about 48 files carry real room descriptions, most scattered across individual wizards' personal directories rather than a complete official town/sect map. The one substantially finished official area is the Kaifeng yamen (衙门) scene, populated by Judge Bao (包拯) and Zhanzhao (展昭). Registration uniquely splits a recovery/admin password from the everyday login password. The apprenticeship/sect system itself works, but no NPC in the shipped content ever actually sets a sect to join.

README

内容亮点

注册流程(两套密码)

英文名字 → 确认建立(y/n)→ 中文名字(2-4 个中文字)→ 管理密码 (≥5 字元,用于遗失普通密码时找回、修改密码,平时不要用)→ 确认管 理密码 → 普通密码(≥5 字元,日常登录用,不能和管理密码一样) → 确认密码 → 民族(0-3)→ 性别(m/f)。

本次修复的关键 bug

管理员账号 / Admin account

管理员名单存储在纯文本文件 adm/etc/wizlist 里;账号本身通过正常 注册流程创建(管理密码另设为 AdminPw1,与登录密码不同)。

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

本地运行

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

游戏端口:40133。

NOTES · 移植与修复记录

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

风云(古龙小说题材),管理密码+登录密码双密码注册流程。新发现的 bug,已收录进 AGENTS.md §7.60:master.lpc 的 log_error()——每一条普通的编译警告(不只是真正的错误)都会调用它——最后会呼叫 CHANNEL_D->do_channel(...);如果 CHANNEL_D 这时候还没有被预载(取决于它在 adm/etc/preload 里排第几个),这次呼叫会在调用者自己还在编译的过程中,悄悄触发对 channeld.lpc 的一次新编译——这个驱动禁止这种嵌套编译,于是抛出"*Object cannot be loaded during compilation.",又被 log_error() 自己捕获并重新记录一次,如此循环,把一条本来毫无意义的 pragma 警告变成了几万行重复的错误堆栈输出。这个问题只存在于 CHANNEL_D 加载完成之前的启动窗口内(之后完全正常),但足以把真实输出淹没到没法看,因此还是修了:在广播前先判断 find_object(CHANNEL_D)。另外也修复了 is_chinese() 和 check_legal_name() 里经典的 §8.1 中文名字 bug(长度界限+字节步进循环,会静默拒绝所有真实中文名字)。排版格式化工具的第三类盲点检查在 12 个命中里抓到了两处真正的损坏(一份巫师培训测验文字档案和一份带有未转义尾随中文注释的代码速查表)——两处都已还原。管理员账号(fluffos/Mud@2026)通过真实注册流程 + adm/etc/wizlist 播种。

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

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

管理员账号 fluffos/Mud@2026(管理密码 AdminPw1,与上面 WASM 摘要记录的 一致)在本仓库当前 checkout 里其实没有实际的存档数据(只有 data/{login,user}/{a-z}/ 的空骨架目录被播种进 git,账号本身的 .o 存档 从未提交)——先用 ls data/login/f data/user/f 验证过,确认为空后,本轮 按 README 记录的凭证通过真实注册流程重新建立了一次(英文 id 沿用 fluffos,登录密码沿用 Mud@2026,管理密码沿用 AdminPw1)。

新手引导先读了 doc/help/newbie.txt:文档描述的注册流程(单一密码→确认→ email→性别→民族)已经过时,与当前 logind.lpc 实际代码不符——真实流程 是 README 记录的双密码版本(英文名→确认→中文名→管理密码→确认→普通密码→ 确认→民族→性别,注册时不问 email)。doc/help/newbie.txt 关于 apprentice/skills/learn/战斗系统的说明与代码基本一致,仅密码段落已 过时,未改动帮助文档本身(内容维护,不在本轮范围)。

用真实中文名字 云舒(英文 id ceshiwo)走完整个注册流程:look/ score/i 在角色创建后、register <email>+decide(風雲用开封府门口的 神仙姐姐 NPC 做真人自助注册,不是 cmds/arch/register.lpc——那个指令需要 (arch) 权限,是给巫师手动帮别人登记用的,一般新玩家永远碰不到,房间牌子 上写的 register your-email 指的是神仙姐姐身上的本地 register/decide 动作)自助完成注册后,均正确响应、无崩溃。

战斗安全陪练机制:cmds/std/fight.lpc 读到确认,判断依据是 obj->query("can_speak")(不是 civilized)——adm/daemons/race/human.lpc 的 create() 无条件把人类设成 can_speak=1,beast.lpc/monster.lpc 两个种族档案都没有设这个属性,因此人形 NPC 走 fight_ob()/fight_ob() 双向切磋分支,兽类/妖魔走 kill_ob() 真杀分支——与本项目本轮反复确认的 "can_speak/civilized 二选一分流"模式一致,本档案用的是 can_speak。现场 用管理员账号对 quest/kaifeng/npc/zhanzhao.lpc(展昭,人类,can_speak=1) 分别测试了 fight(见下方"发现但判定为既有设计"关于死亡的记录)和真实的 可用 NPC 人数极少这一事实本身(见下)。

组织/门派技能获取:organic 与管理员捷径都验证了,但都撞上同一个内容缺口

修复的程序性 bug

发现但判定为既有设计、未改动的现象

未验证事项

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

Independently re-verified against current code rather than trusting the extensive round-one writeup above. All 10+ round-one fixes confirmed still present (code inspection for all, live re-exercise of the highest-value ones — the §7.12 message() type check and the §7.96 START_ROOM fallback, both exercised on literally the first login). Found and fixed one small remaining gap this round's own checklist covers that round one's pass didn't touch.

New fix: adm/simul_efun/file.lpc's cat() still had no null-guard

Round one already fixed log_file()'s assure_file() gap (§7.11) but missed cat()'s separate null-guard need. One-line fix: write(read_file(file) || "");.

Re-verified live: the two highest-value round-one fixes

Verification method

Booted native build-debug driver, admin login (fluffos/Mud@2026) — clean on the first attempt. update /adm/daemons/logind as the real privileged-action check (succeeded). goto /quest/kaifeng/zhengtang as a targeted re-exercise of the make_inventory isolation fix. Two full rapid reconnects, both clean. work/log/debug.log grepped for the original error signatures (Bad argument 4, Wrong permissions, F_SKILL) after the whole session — zero hits; all new log growth was either harmless compile warnings or the already-documented yayi content-gap trace. Driver killed by exact PID after testing; incidental fluffos.o save-timestamp churn reverted before commit.

Files modified this pass

§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). 40 live

replace_program(ROOM); occurrences across 31 files: 26 standalone room-file/heredoc-template lines (real .lpc room files, data/group/groom/*.lpc, feature/up.lpc, quest/kaifeng/qianyafang.lpc) plus 14 string-builder-embedded occurrences (literal \n replace_program(ROOM);\n escape sequences inside generated-code strings) across data/group/obj/ling.lpc, data/group/obj/ling-pai.lpc, a garbled-filename duplicate/backup of ling.lpc under data/group/obj/, and this lib's own room-building tools u/island/obj/roommaker.lpc/u/island/obj/roommaker1.lpc (two copies, both fixed — so newly-built rooms were inheriting the bug too). A full post-fix grep confirms 0 live occurrences remain. Verified via a clean native driver boot (zero new debug.log errors, port listening, killed by exact PID after ~8s).

§7.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): 3 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 three (2026-09-04): shop purchase + 拜师 check

New angle vs prior rounds: live shop + 拜师. Native build-debug driver, port 40133. First send is the English id (no GB/Big5 menu). Admin fluffos/Mud@2026 (wizlist (admin); unused admin-password AdminPw1 this pass). Lands at 世外桃源/REGISTER_ROOM as before.

拜师 — still no legal master (content gap, not a new bug)

Reconfirmed by source: no official NPC set("family", ...) outside u/. apprentice itself is intact. Did not invent a master.

Programming bugs found and fixed this pass

1. is_admin() hardcoded to id island (adm/simul_efun/object.lpc). Wizlist lists lost/island/ fluffos as (admin), and the login banner printed 目前权限:(admin), but is_admin() also required query("id") == "island". clone of anything outside /clone/gift and call both returned 你不能复制物品 / 你不能使用该命令. Aligned is_admin() with is_root(): SECURITY_D->get_status(...) == "(admin)" is enough. Live: call me->set_temp(...) and clone /obj/example/chicken_leg both worked afterward.

2. move() threw on a missing dest path (feature/move.lpc). call_other(dest, "???") on /d/fy/fysquare (never shipped) raised *call_other() couldn't find object and aborted the caller. adm/npc/youxun.lpc create() does that move for the master copy, so the first clone /adm/npc/youxun died at 载入失败. Added file_size + catch before the load; missing dest now returns the existing destination unavailable notify_fail.

3. message_vision() dest int 0 (adm/simul_efun/message.lpc) plus youxun create() announcing after a failed move. After (2), move() returned 0 but create() still called message_vision, and environment(me) was 0, so efun message() got dest int 0 (*Bad argument 3). Guarded message_vision when environment(me) is missing, and only announce in youxun create() when move("/d/fy/fysquare") succeeds. Live: 游讯复制成功,放在这个房间。

4. F_DEALER/F_VENDOR listed missing vendor_goods files via unguarded call_other (feature/dealer.lpc, feature/vendor.lpc). youxun's catalog points at /clone/gift/{feidan,feimao,kuangquan} (directory not shipped); 芳儿/makeupseller point at /d/fy/npc/obj/... (same missing map). list after unlocking can_buy/youxun now prints an empty catalog instead of throwing. Content gap left as-is.

Shop — paid buy verified live

Official town map /d/fy is still missing, so there is no organic walk-up shop. Used the real F_DEALER NPC 游讯 (/adm/npc/youxun, id youxun / you xun): list without the temp flag is the designed refusal 我只卖消息不卖货; after call me->set_temp("can_buy/youxun", 1) the catalog is empty (missing gift files, skipped). Stocked one existing item (clone /obj/example/chicken_leg, id chicken / 烤鸡腿, value 30) via call youxun->set("can_carry", 1) + give chicken to youxun (clone accept_object accepts), funded with clone /obj/money/silver (一两 = 100). buy chicken → 你从游讯那里买下了一根烤鸡腿. Inventory afterward: 六十四文铜钱 + 烤鸡腿 (100 − 30×12/10 = 64; F_DEALER inventory markup val_factor 12). In-session price math + item receipt both confirmed.

Cloned example objects are not autoload; a relog after call me->save() kept the character but dropped the chicken/coins. That is the existing autoload design, not a new save bug. Driver killed by exact PID after the pass. Player-save timestamp churn left uncommitted.

深度功能测试(§10.7,2026-10-04)— negative range ends

scripts/lpc_fix_negative_ranges.py: 4 line(s) in 1 file(s) count a range from the end with < (x[a..-1] -> x[a..<1], x[-2..] -> x[<2..]; KB 06 §7.209). In this driver a negative constant end gave "" / ({ }) and a negative start the whole value, so each of these returned the wrong slice; the compile warning A negative constant as the second element of arr[x..y] is gone from the files that compile. Range lvalues (s[0..-1] = text, the prepend idiom) are left alone. A paired compile of the changed files at HEAD and in the working tree showed no new error.

深度功能测试(§10.7,2026-10-04)— undefined macro and simul_efun gaps

深度功能测试(§10.7,2026-10-05)— 任务表里的 .c 路径与任务守护进程的防护

scripts/lpc_dynamic_quest_guard.py:2 处 spread_quest() 调用(init_dynamic_quest() 的循环里)包进 catch(),缺失的任务物品或编译不过的房间只跳过那一个任务,守护进程照常加载、其余任务照常生成。 验证:adm/daemons/questd.lpc、adm/daemons/tongjid.lpc、quest/tongji/npc/zhuge.lpc、u/lost/cmds/questd.lpc和 cron 守护进程在新进程里加载(HEAD 一次,工作树三次,选房是随机的):HEAD 通过 5 个,工作树三次分别通过 5、5、5 个(共 5 个),无回退。

深度功能测试(§10.7,2026-10-06)— 编译警告整理

scripts/lpc_warnings.py fyzfqyy --fix:无用局部变量 476 个、varargs 7 处、转义 56 处、nosave 函数 15 个改 protected,共改动 220 个 .lpc。HEAD 与工作树分别加载(新进程):211 -> 211 通过,无回退;scripts/lpc_audit_removed_locals.py HEAD 的 5 条候选都是声明被重建或同名 efun(time())。手工:adm/daemons/logind.lpc get_id() 的 string ip = query_ip_number(ob); 只被一段注释掉的站点检查读,删去。启动时警告 145 -> 0;新进程登录(英文名、新人物确认、中文名提示)正常。

深度功能测试(§10.7,2026-10-06)— 与 zhonghua2 同源的三处编译警告

验证:改动的文件和包含 npc/indian 的守护进程在 HEAD 与工作树分别加载(scripts/lpc_listcheck.sh,新进程),无回退。

深度功能测试(§10.7,2026-10-11):dns_master 空 if

深度功能测试(§10.7,2026-10-11):dns_master 空 if

其他体系的属性名(2026-10-15,KB 06 §7.241 第三类,--any-file)

6 个文件(技能、绝招、兵器、书籍、区域 NPC 等)来自侠客行体系(qi/jing/neili),而本库人物是 gin/kee/sen/force:receive_damage("qi", ...) 报 伤害种类错误,query("neili") 永远为 0。按 qi→kee、jing→sen(本库学习/读书指令消耗的就是它)、neili→force、max_neili→max_force、jiali→force_factor 改名(scripts/lpc_port_es_props.py --any-file)。

find_player() 只认在世界里的身体(2026-10-15,KB 07 §8.26)

simul_efun 的 filter_player() 加上 environment(ob):注册中途断线留下的、不在任何房间的身体不再被当成玩家,两个以上时 find_player() 不会再报 The player(<id>) has existed in the world.(wllz3 实测过的问题)。本库若注册流程不会留下带玩家 uid 的身体,这一改动不改变行为。

NPC 带着本库没有的物品,载入失败(2026-10-15,KB 06 §7.73)

2 个文件、3 处在 create() 里 carry_object("<本库没有的文件>")->wear()(或 wield()、set_amount()):carry_object() 得 0,接着的调用报 Bad argument 1 to EFUN call_other(),NPC 根本载入不了,该有它的房间里就少了这个人。多是从别的系统搬来的 NPC 用了原系统的物品路径(最常见:/d/fy/npc/obj/wch_skirt、/d/fy/npc/obj/yafu、/d/fy/npc/obj/sawei)。每处改为 { object carried_ob = carry_object(...); if (carried_ob) carried_ob->wear(); }(scripts/lpc_guard_carry_object.py):NPC 照常出现,只是不带这件东西;文件补回来(或是虚拟对象)照样会带上。载入检查:改动的文件改前能载入 0 个,改后 2 个(2 个原来载入不了),没有退步。

技能基类丢了“预备武功”那一段(2026-10-19,KB 06 §7.262)

feature/skill.lpc 有 skill_map/map_skill(),却没有预备武功(prepare_skill)这一块:变量 skill_prepare、prepare_skill()、query_skill_prepared()、query_skill_prepare()。来自 xkx 系列的 NPC 在 create() 里调用 prepare_skill("cuff", ...),于是 Undefined function prepare_skill 整个 NPC 载入不了。从同系的 xkx100 把这一块原样补回(声明加在 skill_map 后面,函数加在文件末尾),受益 NPC 5 个:quest/kaifeng/npc/tufei2、quest/kaifeng/npc/tufei3、quest/kaifeng/npc/tufei4、quest/kaifeng/npc/tufei5。(scripts/lpc_transplant_function.py)

区域物件的零碎修正(2026-10-19,KB 06 §7.267–§7.271)

逐个物件与 HEAD 对比载入,没有退步。

RANK_D 对 0 的称呼(2026-10-19,KB 06 §7.273)

adm/daemons/rankd.lpc 的 query_respect()、query_rude()、query_self()、query_self_rude() 里 4 个函数开头补上 if (!objectp(ob)) ob = this_object();。NPC 在 create() 里写 "…" + RANK_D->query_respect(this_player()) + "…"(inquiry 对话、chat_msg),驱动自己跑 reset() 时没有人在场,this_player() 是 0。旧驱动里 0->query("age") 返回 0,称呼走默认分支;新驱动直接报 Bad argument 1 to EFUN call_other(),房间的 make_inventory() 吞掉错误,被打死的 NPC 再也刷新不回来。用 scripts/lpc_reach_census.py --walk 找到(xkx100 的武当弟子、一灯、汴梁书生…);修在守护程序里,不动 1,800 个 NPC 文件。

member_array('/', str) 改为 strsrch(str, "/"):字符字面量的 member_array 按字节搜索(2026-10-20,KB 06 §7.283)

member_array('/', str) 里的 '/' 是整数,驱动按 UTF-8 字节搜索,返回字节偏移(带第三个参数时起点也是字节);最新的 FluffOS(923cdbc0)在字符串里有非 ASCII 文字时,对每个调用点警告一次(Warning: member_array(int, string) searches BYTES)。而 str[0..idx-1] 按字符切,中文字符串会在错误的位置截断。改为 strsrch(str, "/")(找不到同样返回 -1,按字符计数;scripts/lpc_fix_member_array_char.py,JSON 编码器等少数几处手改)。改动:/cmds/arch/sameip.lpc(1 处)。

if (x = 常量):条件里写成赋值的比较(2026-10-20,KB 06 §7.290)

if (arg = "button" || arg = "按钮")、if (!arg || arg = "") return 0;、else if (check = 0 && tempB != ""):把 == 写成了 =,条件的值就是那个常量,分支对所有非零数和任何字符串(连 "" 都算)永远成立、对 0 永远不成立,变量还被覆盖;驱动对此没有任何警告。每一处 = 改成 ==(scripts/lpc_fix_cond_assign.py,共 1 处)。改动:/adm/daemons/combatd.lpc(1 处)。

登录密码超过 255 字节:crypt() 抛错(2026-10-20,KB 06 §7.294)

驱动的 crypt() 对超过 255 字节的密钥直接报错(Error in crypt(), check your salt),老驱动则按任意长度散列。在登录提示符下输入 256 字节以上的密码,密码检查那一行就抛错,连线停在一个裸的 > 提示符上,登录走不完(password 指令的旧密码检查同样);用 300 个 x 当参数的扫描发现的。/adm/obj/simul_efun.lpc 里补了一个同名的 simul_efun crypt(key, salt):只有超长的密钥才被截短(先截到 255 个字符,再逐字符截到 sizeof(to_buffer(key)) <= 255,限制按字节算,一个汉字占三个字节),再交给 efun::crypt();普通密码原样散列,已存的密码散列不受影响(scripts/lpc_add_sefun.py crypt)。

get_config(__MUD_PORT__) 经旧版 runtime_config.h 得到字符串(2026-10-20,KB 06 §7.302)

本库的 include/runtime_config.h 是老 MudOS 的编号(整数设置从 15 起,本驱动从 256 起),get_config(__MUD_PORT__) 读到的是另一项设置(字符串),(int) 又只是编译期标注,于是 socket_bind(fd, LOCAL_PORT()) 报 Bad argument 2 to socket_bind(),版本守护进程 port = get_config(__MUD_PORT__) + VERSION_PORT 是字符串相加。头文件自己的注释写明 get_config(__MUD_PORT__) == __PORT__,所以代码里的这个调用(连同外面的 (int) / to_int())改成了驱动的预定义 __PORT__(scripts/lpc_fix_mud_port.py)。改动:/include/getconfig.h(1 处)。

closed 守护的心跳每秒调一次不存在的 versiond(2026-10-20,KB 01 §1.3(c))

closed.lpc 的 heart_beat() 以 if (! VERSION_D->is_version_ok()) return; 开头,本库没有 /adm/daemons/versiond:有人在闭关时,控制台每秒一条 call_other() couldn't find object '/adm/daemons/versiond',闭关的后续处理(load_all_users())也永远走不到。改成 if (find_object(VERSION_D) && !VERSION_D->is_version_ok())(KB 01 的写法:没有版本守护就当版本正常)。加载检查 OK。

NPC 的 chat() 在 chat_msg 为空数组时下标越界(2026-10-21,KB 06 §7.334)

NPC 基类的 chat() 是 if (arrayp(msg = query(...))) { if (random(100) < chance) { rnd = random(sizeof(msg)); if (stringp(msg[rnd])) ...,不检查列表是否为空。本库现有的 NPC 文件里没有字面写成空 chat_msg 的(扫描只认 set("chat_msg", ({ })));守卫挡的是运行时才为空的列表和以后新增的 NPC。在 random(100) < chance 前面加 sizeof(msg) &&(scripts/lpc_fix_chat_empty.py;if (random(100) > chance) return 0; 的写法是 !sizeof(msg) ||)。改动:/std/char/npc.lpc、/std/char/npc2.lpc(共 2 个文件)。

refresh(retask):动词函数不返回 1,搬动或销毁带动作的物件时报错(2026-10-21,KB 06 §7.339)

管理员扫描里 refresh 在重新分布使命之后报 Illegal to move or destruct an object (/questobj/...) defining actions from a verb function(refresh) in object(/obj/user#...) which returns zero.:main() 以第二条 message() 结尾、没有 return,答 0,而 TASK_D->init_dynamic_quest(1) 销毁了给玩家定义过动作(init() 里的 add_action)的使命物件:驱动只在动词答非 0 时才允许这样搬动或销毁,否则它接着遍历的动作表会悬空;答 0 还会让解析器在指令做完之后再补一句“什么?”。main() 末尾加 return 1;(同系已经返回 1 的 11 个同名文件没有动)。

socket:dump_socket_status() 在本库没有(2026-10-21,KB 06 §7.291)

管理员扫描里 socket 指令(/cmds/island/socket.lpc)编译不了:write(dump_socket_status()); 用的是 MudOS 有、本驱动没有的 efun。2026-10-20 的补丁只按名字找了巫师目录里的同名指令,这一条在 cmds/bos、cmds/hufa、cmds/island、cmds/ser 这类目录里;用 scripts/lpc_add_sefun.py dump_socket_status 在 /adm/obj/simul_efun.lpc 末尾补了一个由 socket_status() 构造表格的 simul_efun(没有 sockets 包的构建,比如 WASM,只打印表头)。指令 HEAD 编译失败,现在通过。

坐骑 shape:/cmds/usr/skills 不存在(2026-10-21,KB 06 §7.344)

obj/npc/pet.lpc 的 do_shape() 末尾 printf("/cmds/usr/skills"->pet_skill(this_object()))。本库的 skills 在 cmds/skill/skills.lpc(pet_skill() 就在那里),改成 /cmds/skill/skills。

调用了、但这个库自己的守护进程里没有的函数(2026-10-22,KB 06 §7.354)

MACRO->函数() 调用的函数在这个库的守护进程里不存在:call_other() 对不存在的函数不报错、只返回 0,所以这些功能(时间显示、昼夜事件、名字检查、价格文字……)一直没起作用。同一血统另一个库的同名守护进程里有这些函数,原文照抄到本库守护进程末尾(scripts/lpc_port_function.py;调用处传的参数个数、函数体用到的函数 / 全局变量 / 宏 / 字符串键都在本库里有,已核对;守护进程在 HEAD 和工作区都能加载,每个函数用固定参数各调用一次:HEAD 返回 0,现在返回正常的值):/adm/daemons/chinesed.lpc ← aoxiangtianji:chinese_month()(1 处调用)。

(: 函数 :) 指针指向对象自己没有定义的函数(2026-10-22,KB 06 §7.355)

item_desc / inquiry / chat_msg_combat 里的 (: 函数名 :) 指向本对象(含包含文件、继承的父类)没有函数体的函数:编译不报错,用到时驱动报 *Undefined lfun pointer called: 函数名(look 某物、ask NPC about 话题 直接出错,战斗 / 闲聊里的指针在 NPC 的 chat() 里出错,这一拍心跳的后半段被跳过)。scripts/lpc_scan_callout_targets.py --kinds=lfun。 还剩 1 个函数没有补(other 1):原型还在函数体丢了、或者根本没写过,没有可以直接补回的捐赠(别的库同一路径的文件里没有这个函数,或者它还要用本库没有的辅助函数、签名不同),不编造:/cmds/imm/help2.lpc:confirm_l_choice。

log/ 下的日志子目录没有人建:写日志的 write_file() / log_file() 报错(2026-10-22,KB 06 §7.358)

这个库的代码往 log/ 的 1 个子目录写日志:log/doc/register(cmds/usr/help1.lpc)。压缩包、git clone 和站点包里都没有这些目录(本地启动没有写过它们,gen_keep_dirs.py 没记),write_file() 对不存在的目录抛 *Wrong permissions for opening file /log/dlog/money for append. "No such file or directory",调用它的函数在写日志那一行中断,后面的奖励、标志、步骤都没有执行。本库的 log_file() 会自己建目录(实测,或读源码:nitan 系的 assure_file()),所以这里只记了直接用 write_file() / save_object() 写的目录。把 log/doc/register 记进 scripts/wasm_keep_dirs.txt(scripts/lpc_keep_log_dirs.py;站点和 pristine 树按它建空目录)。证明(scripts/lpcc_eval.py,在 /adm/daemons 这类目录下的求值对象里写 /log/zzdirprobe/...,新进程)见 KB 06 §7.358 的实测表。

长度检查按字节写,旁边的提示按汉字写:4 处(2026-10-22,KB 06 §7.362)

老档的 strlen() 数字节(一个汉字 2 字节),转成 UTF-8 后它数字符:提示写「必须是 2 到 6 个中文字」的检查还是 strlen(name) < 4 || strlen(name) > 12,于是两三个字的房名、帮会名、群名、聊天室名、称号被提示自己说允许的那句话拒绝,上限却是提示的两倍;留言板的标题检查 i < 4 || i > 24 || i % 2 还会拒绝所有奇数个字的标题(post 你好吗)。本库 4 处(2 个文件):if ((strlen(name) < 2) || (strlen(name) > 40)) {(/adm/npc/caifeng.lpc:163)。scripts/lpc_fix_strlen_gate.py 以提示为准:条件里每个 strlen 门槛都恰是提示所说数字的两倍才折半,存长度的变量(i = strlen(arg);)的门槛和 || i % 2 奇偶项、其后循环的 i % 2 == 0 && 一并处理;提示里有英文 / 字母 / 字节的不动。证明(scripts/lpcc_eval.py,bxsj 的留言板,求值对象继承 NPC 并重写 edit() 记录调用,command("post 标题")):HEAD 拒绝「你好」和「你好吗」、放行 23 个字的标题;改后接受前两个、拒绝第三个;shenmo 的 named.lpc invalid_new_name("张三"):HEAD 回 名字只能是2-4个中文字。,改后回 0。抽样 24 + 15 个库的 HEAD / 工作树加载对比 0 退步。

按字节写的汉字循环、茶馆猜诗和同盟频道标题(2026-10-23,KB 06 §7.363)

老档按字节做「一个汉字」:while (i--) if (i % 2 == 0 && !is_chinese(name[i..<0])) 只检查偶数下标,奇数位上的拉丁字母(张a)会过;茶馆猜诗 mixup() 用 strlen(str)/2 再 j=j+j、str[k..k+1] 交换两字节;泥潭系 channeld 的 switch (strlen(fname)) case 4/6/8/10 和 strlen(family)==4/6 按字节长度给同盟 / 门派名加空格。本驱动的 strlen() 和区间都按字符算。scripts/lpc_fix_byte_char.py:去掉奇偶项、把区间改成 name[i..i],按字符重写 mixup() 并把 strlen(first)>=14 折成 7,频道标题的 case / 门派长度改成字符数(对照 aoxiangtianji)。本库 汉字循环 / is_chinese 区间 7 个文件;channeld 同盟 / 门派标题 1 个文件。证明(scripts/lpcc_eval.py):sjplii 的 check_legal_name 在 HEAD 接受「张a」、改后拒绝,两边都接受「张三」;xkx100 的 clubpoem->mixup("离离原上草") 得到「离离原草上」(真交换汉字);nitan_san 两字同盟名得到 【 兄 弟 】。关键对象加载通过。

中文名 / 验证码仍按 GBK 取「两字节一字」(2026-10-23,KB 06 §7.373)

pname = pname[(random(sizeof(pname)) & 0xFFFE)..<1]; pname = pname[0..1]; 在按字符计下标时会取出两个汉字。scripts/lpc_fix_pname_slice.py 去掉掩码并把收尾改成 [0..0](pname/pname2/sec_name/str/str1)。本库 4 处。证明:nt1 生成名长度 2–4;HEAD 常见 3–5。

无参数时命令对 0 的调用(2026-10-27,KB 06 §7.336 Also)

巫师/管理员命令在通过权限门之后仍会把 0 交给 sscanf / read_file / find_living 等。lpc_fix_bare_arg.py 在首次使用参数前加上 if (!arg)(或 help(me) / GetHelp())。本库本批改动见该提交。

深度功能测试(2026-10-27,§6.10 未知 pragma save_binary/optimize)

删除本库中 FluffOS 不认的 #pragma save_binary / #pragma optimize… 行。