info.html · 介绍 · play.html · 游玩 · llms.txt · 下载与本地运行 · ZIP · GitHub
A Star Wars-themed conversion built on top of the Lima mudlib (this collection's own libs/lima, 164) -- its own README describes it as a set of 'additions and changes to the base mudlib' meant to be installed over a full Lima install, which is how this copy was assembled. Ships a genuine Star Wars race roster (13 playable races spanning several human ethnicities plus aliens such as Wookiees and Twi'leks), its own combat/limb/wound system, guild-style character classes (Jedi, smuggler, bounty hunter, and more), crafting, and weapon/armor/lightsaber item trees. New characters land in a working fallback starting room, since the original Star-Wars-specific starting area was never included in this particular git archive. Makes a genuine outbound network connection to the public Intermud-3 router at every boot.
README
A Star Wars-themed LPC mudlib built as an extension of the Lima mudlib (<https://limalib.dev>, FluffOS's own official reference/framework mudlib). Its own README describes it exactly: "This project only includes additions and changes to the base mudlib. It must be installed over the current Lima mudlib." So that's how it's built here: a full copy of this project's already-converted libs/lima/work/ (164, port 40212) with swmud's own ~980-file tree overlaid on top (852 new files, 233 overriding same-path Lima files).
Source: git clone https://github.com/coupdeforce/swmud (last pushed
2016-02-16, commit cf33a51). Slug swmud, number 180, port 40227.
Highlights
- A from-scratch Star Wars race roster (13 playable races: alderaanian, corellian, defel, ithorian, jawa, lorrdian, mon calamari, nabooan, tatooinian, twi'lek, verpine, wookiee, ysanna -- several of them distinct human ethnicities from different planets), its own combat/ limb/wound system (
std/adversary/*), guild classes (jedi, smuggler, bounty hunter, diplomat, engineer, physician, slicer, assassin, merchant), a crafting/manufacturing system, and item trees for weapons, armor, and lightsabers -- all genuinely new content built on top of Lima's engine (parser, security model, wish shell, etc). - Real character creation: race selection -> point-buy attributes -> dominant hand -> Imperial/Rebel/Neutral team alignment -> lands in the game with a starting body.
- Porting it surfaced a large cluster of dropped macro definitions (mudlib.h/classes.h/commands.h/daemons.h/config.h each independently rewritten by swmud, apparently trimmed by hand at some point without checking every caller still in the tree) and one genuine ordering bug in the character-creation code that crashes the very first player ever to register on a fresh install. Full list in
NOTES.md. - The real Star Wars starting area (
/d/coru/main, "Coruscant") was never included in this archive at all -- confirmed absent from both the git history and the raw clone. Players land in a real, working fallback room (/d/common/void, "Void") instead; seeNOTES.md.
Registration flow
new name -> "Is '<Name>' correct?" -> password -> confirm password ->
gender (male/female) -> email -> real name -> homepage (optional) ->
race selection (type a race name, or list/help races/help stats)
-> point-buy attributes (a <stat> [n] / s <stat> [n], done when
satisfied) -> dominant hand (left/right) -> team (imperial/rebel/
neutral) -> lands in Void with a starting body, 1000 XP, and a
$N the Bantha Fodder title.
Admin account
- id:
fluffos - password:
Mud@2026
Created through the mudlib's own real first-boot bootstrap (Lima's
"whoever registers first on an empty install becomes admin" convention,
inherited by swmud's sw_body_handle_new_logon()) -- not a save-file
hand-edit. Verified live: who shows Role Admin Wizard; update
/std/race/wookiee and admtool (including its wizard-gated priv 1
submenu) both succeed.
Status
Boots clean. Verified live with a real driver session and a raw socket
client: full registration (both a wizard-bootstrap account and a second,
ordinary account), race selection across multiple races, point-buy
attribute allocation, look/score/who/inventory, admin update/
admtool, and a clean quit, all producing correct output.
1731 of 1860 .lpc files pass a full lpcc_check.sh-style batch compile
sweep. Nearly all of the 129 that don't are orphaned Lima demo content
(domains/'s stock example rooms/monsters/spells, std/sword.lpc,
std/race/unused/troll.lpc, etc. -- content swmud's own game world never
uses and that predates this port) hitting the same "swmud rewrote the
item/combat API out from under Lima's original demo files" incompatibility
documented repeatedly in NOTES.md. See NOTES.md for the full
breakdown and what's left unfixed on purpose.
WASM status: playable. The specialized Lima-flavor WASM driver
(same NO_ADD_ACTION/NO_WIZARDS/NO_LIGHT build as native lima/swmud)
is now packaged per-lib via scripts/custom_drivers/lima_swmud/, so the
site can actually boot this game. Registration, race selection, and world
entry were verified in-browser; see NOTES.md 「站点基础设施缺口已补上」.
⚠️ Makes a real outbound network connection at boot. `daemons/
imud_d.lpc` preloads and connects to the public Intermud-3 router
network at every boot (ADMIN_EMAILininclude/config.his a real-
looking value, so Lima's placeholder-based protective guard doesn't
block it). Do not include this lib in high-frequency automated re-boot
loops. See NOTES.md.Local run
cd libs/swmud
~/src/fluffos-lima/build-debug/src/driver config.fluffosImportant: this lib needs the same specialized Lima-flavor driver
build as libs/lima/ (~/src/fluffos-lima/build-debug, built with
NO_ADD_ACTION/NO_WIZARDS/NO_LIGHT defined, OLD_ED/PACKAGE_UIDS
undefined) -- it will NOT boot on this project's shared default driver
at ~/src/fluffos/build-debug. See libs/lima/NOTES.md for how that
driver was built, if the checkout needs to be recreated.
Game port: 40227.
NOTES · 移植与修复记录
swmud -- Star Wars Mud
Source: git clone https://github.com/coupdeforce/swmud (HEAD at clone
time: cf33a51, last pushed 2016-02-16, cloned 2026-08-26). Number 180,
slug swmud, port 40227. Status: done (clean boot, real registration
+ character creation + look/score/who/inventory/admin update/
admtool/quit all verified against a live driver).
Architecture: this is not a standalone mudlib
swmud's own README says it outright: "This project only includes
additions and changes to the base mudlib. It must be installed over the
current Lima mudlib." Confirmed by inspection -- the raw clone is ~980
files with no secure/simul_efun.lpc combiner, no check_config.lpc,
no get_root_uid()/master security scaffolding, and macro tables
(include/mudlib.h, classes.h, commands.h, daemons.h) that
reference dozens of paths outside the archive. This project happens to
already have a full working copy of Lima itself onboarded
(libs/lima/, 164, git clone https://github.com/fluffos/lima) from
earlier this session, so the AGENTS.md \S2.1 "recognize the lineage"
playbook applies directly, just at a larger scale than usual:
1. work/ = a full copy of libs/lima/work/ (already fixed for this
driver -- see libs/lima/NOTES.md), with every file from swmud's own
converted tree overlaid on top. 852 files are swmud-only additions;
233 override a same-path Lima file outright (secure/master.lpc,
secure/daemons/secure_d.lpc, std/body.lpc and 14 of its body/*
submodules, std/adversary/*, most of cmds/verbs/cmds/player,
the trans/cmds "wish" shell command tree, include/*.h, etc).
2. Because this driver requires a different build for anything
Lima-based (NO_ADD_ACTION/NO_WIZARDS/NO_LIGHT defined,
OLD_ED/PACKAGE_UIDS undefined -- see libs/lima/NOTES.md \S
"驱动编译选项冲突"), swmud reuses that exact driver checkout,
~/src/fluffos-lima/build-debug. It will not boot on this
project's shared default driver.
3. Encoding: swmud's own raw clone is 100% ASCII/UTF-8 except one Latin-1
copyright symbol (©) in help/wizard/coding/parser, fixed with
iconv -f ISO-8859-1 -t UTF-8 (note: plain -f latin-1 fails with
"failed to start conversion processing" on this machine's iconv --
use the full charset name ISO-8859-1). scripts/convert_lib.sh ran
with UTF-8 as the source encoding (i.e. rename + reference-fixup
only) against a staging copy, then that staging tree was rsync'd
onto the pre-populated work/ (never run convert_lib.sh directly
against work/ here -- it deletes and recreates its target from
scratch, which would destroy the Lima base).
Because two independently-evolved snapshots of a large, deeply inheritance-based codebase are being combined, most of the real bugs below are API mismatches between vintages -- a file on one side of the merge calls a function/macro/class that the other side renamed, dropped, or never had -- rather than classic single-archive conversion bugs. Two consistent patterns run through almost everything below:
- **swmud's own
include/*.hrewrites silently dropped macros that swmud's own files (or unmodified Lima files still in the merged tree) still reference.** Every one ofmudlib.h,classes.h,commands.h, anddaemons.his swmud's own full replacement of Lima's original (confirmed: none of the 233 overridden paths above are byte-identical to Lima's copy), and each one is missing entries the *other* side of the merge needs. This is not something the conversion introduced -- it's a pre-existing internal inconsistency in the real swmud archive, the same class of gap as dsI's missingLIB_*macros (seelibs/dsI/NOTES.md) -- just spread across many headers instead of one. - **swmud rewrote several core object-model files (
std/modules/ m_damage_source.lpc's weapon-damage API,std/adversary/*'s whole combat/limb system, item base classes) with a different API than Lima's originals, orphaning Lima's own demo content that still calls the old API.**domains/(Lima's stock example rooms/monsters/spells: Grand Hall wizard start,V_Plains, the caves/labyrinth/beach demo areas,fireball/magic_arrow,troll/orc/goblin/dragon/wolf) and a handful of genericstd/*.lpcfiles (sword,torch,armour,meat,paper,water,light_object,lantern,combat_spell,moving_monster/wandering_monster/following_monster/aggressive_monster,loot_chest,fluid) are not part of swmud's real Star Wars game world (that lives in the top-leveld/tree anddomains/std/{ammo,weapon,crafting,monster,spells,rooms,...}content that *swmud itself* authored) -- they're leftover Lima teaching/demo content that happens to still be present in the merged tree, was never touched by swmud's own commits, and is not wired into swmud's actual gameplay. 77 of the 129 remaininglpcc_check.shfailures are exactly this category. Confirmed non-canonical by cross- referencing: none of these files are byte-different fromlibs/lima/ work's copy, and nothing in swmud's real content (d/, the SW-nameddomains/std/*subtrees) inherits or references them. Left unfixed, same as this project's standing policy for pre-existing content/ design gaps (see e.g.libs/lima/NOTES.md's ownWWW/cgi/*/contrib/ marriage/*entries, orlibs/dsI/NOTES.md's "declare war" gap).
Real bugs fixed (driver-compat / programming, not content)
1. Dropped macro definitions (the single biggest bug class)
Systematic sweeps (grep every inherit BARE_MACRO;, new(MACRO...), and
MACRO->call() site against every #define in include/*.h) found and
fixed:
include/daemons.h: 9 missing daemon-path macros for daemon files that do exist (CRAFTING_D,DOMAIN_D,EMOJI_D,LOOT_D,MEMCHECK_D,PARTY_D,RST_D,STATE_D,TASK_D) plusXTERM256_D(used bystd/modules/m_colours.lpc/m_frame.lpc/m_triggers.lpcfor ANSI color support).include/mudlib.h: ~40 missing object-path macros across several waves of discovery --M_FRAME(dropped despite 7cmds/player/*files still inheriting it, and the module file itself still present unmodified from Lima); the wholeM_COLOURS/M_CRAFTING/M_DICE/M_HEALING/M_LOCKPICK/M_POWER/M_REACT/M_READY/M_SALVAGEABLE/M_SPECIAL_WEAPON/M_STATEFUL/M_TRAINER/M_WIDGETSmodule family (all present as real files, all in Lima's original table, all missing from swmud's); the whole "high-level inheritable" family (ARMOUR,AMMUNITION,BANDAGE,BATTERY,BEHAVIOUR_TREE,BOARD_OB,CRAFTING_STATION,DRINK,ELEVATOR,JUNK,MATERIAL,MATERIAL_SPAWNER,RANGED_WEAPON,SLOWHEAL,TAMING_COLLAR,TRANSIENT,ART_OBJECT,GEM,PELT);HEAVEN; menu/shell plumbing (PARTY_MENU,PLAYER_SHELL-- an exact duplicate of swmud's own renamedPLYR_SHELL, still needed by unmodifiedsecure/user/shell.lpc,TASKTOOL,USER_MENU,CONFIG_EDITOR,CMD_OB_TASKTOOL, and the wholeCMD_OB_{EMOJI,FRAMES,METRIC,MODE, SIMPLIFY,WIDTH}family used byobj/mudlib/plmenu.lpc); and three application-specific paths inferred from their sole call sites rather than a Lima precedent (CRAFTING_ITEMS=/domains/std/crafting/,IMUD_CHANNELT_DUMMY=/obj/mudlib/ichannelt,MAKER=/contrib/roommaker/buildmenu,SNOOP_DUMMY=/obj/secure/ snoop_dummy).include/classes.h:CLASS_EFFECTandCLASS_WEAR_INFO(both target files --std/classes/effect.lpc,std/classes/wear_info.lpc-- present and unmodified; swmud's ownstd/living/effects.lpcandstd/adversary/armour/limbs.lpc/cmds/player/equip.lpcstillinheritthem by macro name).include/commands.h:TRANS_ADMINCMD_DIR/CMD_DIR_ADMIN(target dir/trans/admincmdspresent and populated -- without this,trans/obj/wish.lpc'sADMIN_CMD_DIRSmacro expansion produced a syntax error that cascaded into wrecking parsing for the rest of the file, breaking the wizard "wish" shell object entirely).include/config.h:METRIC/KG_TO_LBS/LBS_TO_KG(needed by the restoredweight_to_string(), see \S2 below, and by swmud's ownstd/modules/m_companion.lpc).
All confirmed by checking the target file actually exists in the merged tree before adding the macro back -- none of these paths were invented.
2. Dropped simul_efun functions
swmud's own secure/simul_efun/{misc,objcalls,path,string}.lpc (4 of
the 4 simul_efun source files it ships) replaced Lima's originals
wholesale, but are an older/leaner snapshot missing several utility
functions that both Lima-base files *and swmud's own files* still call:
lima_version()/identify() (misc.lpc; called by secure/
error_handler.lpc and the version command), file_domain() (path.lpc;
called by daemons/domain_d.lpc), and punctuate()/tidy_list()/
time_to_string()/weight_to_string()/filepath_ellipsis() (string.lpc;
called by 14+ files including cmds/wiz/calls.lpc and swmud's own
std/modules/m_companion.lpc). Ported the exact implementations forward
from libs/lima/work/secure/simul_efun/*.lpc (unmodified copy-paste,
credited in-file) rather than reinventing them.
Also found the exact same already-known bug Lima itself had and
fixed upstream: secure/simul_efun/string.lpc's create() builds an
"every byte value" lookup table via chr(i) for i in [0,256); this
driver's sprintf("%c", 0) (used by the chr() simul_efun override
itself) errors on a \0/out-of-range codepoint. Lima's own current
string.lpc already fixed this (for (i = 1; i < 255; i++)); swmud's
copy had reverted to the original [0, 256) range. Applied the exact
same fix Lima uses, verbatim, rather than re-deriving a different one.
3. TYPE array NAME / bare array dialect (§7's recurring bug class 7)
980 sites across swmud's own files used two flavors of the classic old-
MudOS array-declaration dialect this driver doesn't accept: TYPE array
NAME (405 hand-written + machine-verified sites, e.g. string array
names;) and **bare array as a shorthand for mixed *** (a second,
narrower dialect specific to this archive -- ~200 more sites, e.g.
array args..., array handle_ob(...), class command_info array
module_commands()). A two-pass scripted sweep converted both to modern
TYPE *name / mixed *name syntax. Two sweep-tooling bugs surfaced and
were caught by re-running lpcc_check.sh and fixing forward rather than
trusting the first pass:
- The bare-
arrayregex needed a trailing word-boundary; without it,arrayp(andarray_sum((two real identifiers that happen to start with the substringarray) got mangled intomixed *p(andmixed *_sum(. Fixed by reverting those ~80 specific corruptions with a targeted second pass, then adding the missing\b.secure/simul_efun/json.lpc's own header comments (a "v1.0.2: define array keyword for LDMud... v1.0.4: Removed array keyword" changelog) independently confirm swmud is a snapshot from *before* upstream Lima cleaned up exactly this same LDMud-stylearrayshorthand -- this wasn't a guess, it's the archive's own documented history. - Class-typed arrays (
class event_info array queue,class command_info array module_commands()) got the wrong substitution (class event_info mixed * queue-- two type keywords in a row); the correct transform for aclass X arrayprefix isclass X *, notclass X mixed *. Fixed with a second targeted pass matching theclass IDENT mixed \*pattern this produced. - One residual case (
std/object/visible.lpc'svoid remove_id(string array ...);, a *typed* varargs ellipsis) needed theTYPE *...form, not the bare-array sweep'smixed *...-- fixed by hand (only one instance existed).
4. inherit chain size too small once merged (masqueraded as infinite recursion)
/std/body.lpc failed every load attempt with `*Inherit chain too deep:
N for every N` up to 200 tried -- looked like true runaway recursion,but the real cause (found by bisecting) was a missing file:
std/body.lpc has inherit __DIR__ "body/help";, and std/body/
help.lpc does not exist anywhere in this archive or in Lima's base.
Compiling a missing inherit target routes through master.lpc's
compile_object() virtual-object fallback, which (per its own doc
comment) walks up the path looking for a parent .lpc to call
virtual_create() on -- for /std/body/help that parent is /std/
body.lpc itself, so resolving the missing inherit re-entered compiling
/std/body.lpc, which needed to resolve the same missing inherit again,
forever. Removed the dead inherit __DIR__ "body/help"; line (content
genuinely absent, not invented) and also inherit __DIR__
"body/wiz_position"; on the same line block -- confirmed *not* just
missing but actively dead: std/body/wizfuncs.lpc's own header says
"230319, Tsath: Merged wiz_positions into this file," and it already
defines query_wiz_position()/set_wiz_position(). inherit chain
size was still bumped from Lima's 30 to 60 (this project's common
ceiling, used by 137 other libs) as normal headroom for the now-much-
larger combined class hierarchy -- it just wasn't the real bug.
One related, still-orphaned file: std/modules/m_exit_obj.lpc (from
Lima's base, unreferenced anywhere in the merged tree -- grep confirms
nothing inherits M_EXIT_OBJ) calls a 3-argument eval_dest(), but
swmud's own replacement std/modules/m_exit.lpc defines a completely
different 1-argument eval_dest() (also private, matching the
AGENTS.md \S7.48 cross-file-private pattern -- loosened to protected
on general principle, though no live caller actually needs it). Left
m_exit_obj.lpc as a known lpcc_check.sh failure: it's genuinely dead
code with an incompatible signature from a different API vintage, not
something to guess a 3-argument implementation for.
5. First-ever player registration crash (real, 100%-reproducible)
The single most severe bug found: every fresh install of this archive
crashes on the very first character ever created. secure/user/
sw_body.lpc's sw_body_handle_new_logon() auto-promotes the first-ever
registrant to admin (a direct port of Lima's own bootstrap convention)
*before* calling create_body(). Inside std/body.lpc's create() ->
adversary::create() -> mudlib_setup() -> refresh_stats() ->
std/adversary/health/limbs.lpc's set_max_health(), the racial-stat
rollout calls check_wizard_set() (an anti-cheat guard meant to stop a
*different*, low-ranked wizard from remotely tampering with another
player's stats). That guard's thing != link check is unconditionally
true at this exact point in the call chain, for *every* new character
of *any* account, because link is only ever assigned later, inside
enter_game()/init_cmd_hook() -- which hasn't run yet during the
body's own constructor. For an ordinary (non-wizard) new account this is
harmless (wizardp(thing) is falsy, so the guard short-circuits), but
for the bootstrap-admin account -- unavoidable on a fresh install, and
also would hit any wizard creating a new character if this mudlib ever
supported more than one character per account -- wizardp(thing) is
truthy and the guard fires: *Invalid attempt by <name> to set 's max
health to <n>. This took real trace-level debugging to isolate (naive
write()/printf() debug statements silently vanished at exactly this
point in the call stack, because this_player() context is ambiguous
mid-construction; switching to write_file()-based logging and reading
/log/runtime's actual stack trace was what nailed the true call
chain -- see git history of this fix for the full reasoning if this
class of bug recurs elsewhere). Fixed with a one-line, minimal guard:
only apply the anti-cheat check once link is actually established
(if (link && ...) instead of just if (...)), preserving the real
anti-cheat behavior for its intended post-login use case.
6. Division by zero in the Character Creation attribute screen
std/modules/m_bodystats.lpc's query_for() (the "Force" stat, with a
Star-Wars-specific environmental bonus term) divides by cur_for
unconditionally -- but cur_for is legitimately 0 for every freshly
rolled, not-yet-allocated character, which is exactly the state the
attribute-point-buy screen displays. Crashed the Character Creation
"Attributes" screen for every single new character on every single
render until the player had already put at least one point into Force.
Fixed with a guard returning cur_for unmodified (0) rather than
dividing by it, on the reasoning that a character with 0 force
sensitivity shouldn't receive an environmental force bonus anyway.
7. team_alignment used but never declared
obj/mudlib/createmenu.lpc's Character Creation "Team" step
(imperial/rebel/neutral) calls this_body()->set_team_alignment(n), and
secure/daemons/{user_d,finger_d}.lpc's who/finger display code reads
"team_alignment" back as a plain global variable via this driver's
fetch_variable() reflection mechanism -- but no team_alignment
variable, nor set_team_alignment()/query_team_alignment() functions,
exist anywhere in the archive. The setter calls were pure no-ops
(call_other to an undefined function silently returns 0), and every
who/finger lookup on *any* character crashed outright (*Variable
named 'team_alignment' does not exist or is not visible!) since the
variable genuinely doesn't exist to reflect. Added the missing
int team_alignment; variable plus matching accessors to std/
body.lpc, mirroring how race_name already works as a plain reflected
variable on the race classes. (The broader legal_body_query list in
user_d.lpc also names 8 jedi-sponsorship fields -- jedi_sponsor,
sponsored_by, etc -- that are similarly never declared anywhere; left
alone since they're outside the everyday who query set that actually
gets exercised, per secure/daemons/finger_d.lpc's own shorter
12-field list, so they're not a live crash. Flagged here in case a
future jedi-sponsor-specific command surfaces the same gap.)
8. race_name missing from 4 leftover Lima races -> crashed who
std/race/{human,elf,orc,documentation}.lpc are unmodified Lima base
files (byte-identical, confirmed via diff) that hardcode query_race()
to return a literal string instead of exposing a race_name variable
the way every one of swmud's *own* races does (human_corellian,
wookiee, defel, etc. all declare string race_name = "...";).
who/finger's variable-reflection lookup on race_name crashed for any
character of one of these 4 races the same way \S7 did for
team_alignment. Since these 4 races are also non-canonical for a Star
Wars game (a generic "human"/"elf"/"orc" alongside swmud's own 13 real
races, one of which -- human_corellian et al -- already covers
"human" properly) and were the same 4 files needing the stat_roll_mods
class-inherit fix below, moved them to std/race/unused/ (an existing,
already-used-for-this-purpose directory -- human_dathomirian.lpc was
already there) alongside troll.lpc (\S9). race_d.lpc's own
get_dir(DIR_RACES + "/*.lpc") glob is non-recursive, so this cleanly
removes them from the selectable race list without deleting any content.
9. Missing inherit CLASS_STATMODS; broke 5 races' stat-roll class
std/race/{human,elf,orc,troll,documentation}.lpc (all unmodified Lima
files) declare a local class stat_roll_mods query_roll_mods() function
using a class type defined in std/classes/statmods.lpc, but never
inherit CLASS_STATMODS; to bring that class definition into scope --
a real, lpcc_check.sh-confirmed compile failure (Undefined class
'stat_roll_mods') for all 5. Added the missing inherit to all 5. 4 of
the 5 (everything except troll.lpc) now compile clean and were kept
loadable (before being moved to unused/ per \S8 above, for the
separate race_name reason). troll.lpc has a second, deeper
incompatibility (below) and stays broken.
10. troll.lpc (leftover Lima demo race) broke 3 *real* swmud races
std/race/troll.lpc additionally calls set_to_hit_bonus()/
set_weapon_class() -- functions that existed in Lima's old combat
system but don't exist anywhere in swmud's rewritten std/adversary/*
combat model (\S"Architecture" above). This alone would just mean troll
fails to load and gets skipped -- except daemons/race_d.lpc's
create() loop does if (!load_object(tmp)) { continue; }, and on this
driver a failed compile inside load_object() throws an error that
propagates past that if/continue guard instead of returning falsy,
aborting the entire foreach early. Since get_dir() returns races in
filename order and troll.lpc sorts right before twilek.lpc,
verpine.lpc, and wookiee.lpc, this silently dropped 3 of swmud's own
*real, working, Star-Wars-canonical* races from the selectable list
every single boot -- not a cosmetic listing bug, an actual "3 valid
races become permanently unselectable" bug, caused entirely by one
broken leftover demo file sorting adjacent to them. Fixed by moving
troll.lpc to std/race/unused/ (same mechanism as \S8) rather than
trying to guess a set_weapon_class()/set_to_hit_bonus()
implementation for content that was never part of this game to begin
with. Verified live: the race list now shows all 13 real races,
including wookiee/twi'lek/verpine, and each is independently selectable.
11. WIZARD_START pointed at broken Lima demo content
include/config.h's WIZARD_START (upstream value: "/domains/std/
Wizroom", Lima's stock "Grand Hall" demo room) fails at runtime: its
set_objects() places a virtual "map" object at /domains/std/
map.lpc, which calls set_untouched_desc() -- again, a function that
doesn't exist anywhere in swmud's rewritten object API (same pattern as
\S10). This crashed move_to_start() for the wizard-fallback path
specifically -- i.e. exactly the path this project's own admin-account
verification convention exercises. Repointed WIZARD_START at
/d/common/void (a real, working room this archive does ship) instead
of inventing replacement demo content. This is a deployment
substitution, not a "fix" of swmud's own design, since \S12 below means
the *real* wizard starting room was never included in the archive
either way; ordinary (non-wizard) players already fall through move_
to_start()'s own built-in fallback chain to this same Void room for
that reason, so wizards now land in the same well-defined place.
12. The real starting area doesn't exist in this archive at all
include/config.h's START/NEW_PLAYER_START point at /d/coru/main
("Coruscant", the intended real starting location) -- but neither that
file nor even a d/coru/ directory exist anywhere in the raw clone or
its git history. This is confirmed not a conversion artifact: the
d/ tree (swmud's real, non-Lima game-content root) has real, working
subtrees for items/weapons/armor/monster templates (d/arm, d/buffs,
d/com, d/const, d/mon, d/obj, d/weap) but no room/area
content anywhere -- confirming the actual playable map was never
committed to this git repository at all (plausibly built live on the
original production server and never checked in, a common split for
"engine code" vs "game content" in MUD codebases). This is a genuine,
severe, pre-existing content gap -- not something fixable within this
project's "fix programming bugs, don't invent content" mandate.
Fortunately std/body/start.lpc's move_to_start() already has a
sensible built-in fallback chain (configured start -> WIZARD_START/
START -> VOID_ROOM) ending at a real, well-written room
(/d/common/void.lpc, "Void... This is where players and objects are
moved to when something goes wrong. If you end up here, please let a
wizard know."), so every new character still lands somewhere coherent
and playable rather than crashing -- this was the intended behavior of
swmud's own error-handling design, not a workaround this port invented.
13. secure/user/sw_body.lpc's new-character shell path clamp broke wizard commands
Every brand-new character's shell (incarnate(), in the if (is_new)
block) unconditionally overwrote its shell's "path" variable to
({"/cmds/player", "/cmds/guild"}). secure/user/shell.lpc's
start_shell() already correctly picks WIZ_SHELL (the Lima "wish"
shell, /trans/obj/wish, whose own create() smartly defaults path
to WIZ_CMD_DIRS/ADMIN_CMD_DIRS for a wizard account) vs
PLAYER_SHELL based on wizardp() -- but the very next thing
incarnate() did was stomp that smart default back down to the plain
player command set, for every new character regardless of wizard
status. Combined with \S5's bootstrap-admin-before-create_body()
ordering, this permanently locked the very first player on a fresh
install (guaranteed to be a wizard) out of every wizard/admin command
(update, admtool, ...) forever, since this mudlib is single-
character-per-account (no way to "recreate" the character with a wider
path later). Fixed by only clamping the path when !wizardp(query_
userid()), letting a wizard's shell keep whatever WIZ_SHELL's own
constructor already set up. Verified live: update /std/race/wookiee
and admtool (through its wizard-gated priv 1 submenu) both work
correctly for the bootstrap-admin account after this fix.
14. NO_NEW_PLAYERS -- deployment change, not a bug fix
include/config.h ships with #define NO_NEW_PLAYERS (an intentional
upstream "closed beta" gate -- new registrations are rejected outright
except via a pre-approved guest slot). Since this project's whole point
is letting site visitors register and actually play, #undef'd it.
Documented in-file as a deliberate deployment substitution, matching
this project's established convention for this exact situation.
15. Missing <lpscript.h> header (removed, not invented)
swmud's own include/mudlib.h replaced Lima's #include
"custom_mudlib.h" (an empty upstream placeholder) with #include
<lpscript.h> -- a header that doesn't exist anywhere in this archive
*or* in Lima's base, breaking compilation of every single file (it's
pulled in via the global include chain). The only 3 references to
LPscript anywhere in the merged tree (daemons.h's LPSCRIPT_D path
macro, secure/master.lpc's compile_object() handling a hypothetical
*.scr file extension, and this include line) need zero symbols from
the missing header -- there are no .scr files anywhere in the archive
either, so the code path is dead in practice. Removed the #include
line rather than fabricating a header for a feature this archive never
actually ships content for.
Known, deliberately unfixed gaps (content/design, not bugs)
- \S"Architecture" above: ~77 of 129 remaining
lpcc_check.shfailures are orphaned Lima demo content (domains/'s stock rooms/ monsters/spells, plusstd/sword.lpcand siblings) that predates this port and isn't part of swmud's real game world. Not fixed, matching this project's standing "don't invent content" policy. std/modules/m_exit_obj.lpc(\S4): dead code, incompatibleeval_dest()signature from a different API vintage, nothing references it. Not fixed.std/race/troll.lpc(\S10, now instd/race/unused/): incompatible old-Lima combat API calls (set_to_hit_bonus/set_weapon_class). Not fixed -- not a real Star Wars race to begin with.obj/mudlib/nicknamemenu.lpc: one real, fixed bug (missinginherit CLASS_ALIAS;for itsclass aliasusage -- applied), but the file has additional pre-existing gaps beyond that ((: new_template :)/(: rcv_new_alias_name :)reference functions that don't exist anywhere in the file or its inherits) that look like a genuinely incomplete/abandoned feature in the original archive, not a conversion artifact. Left as a knownlpcc_check.shfailure -- nickname aliasing is a peripheral QoL feature, not exercised by this port's core verification path.obj/usermenu/usermenu.lpc: an alternate, apparently-unused character-creation menu system (nothing in the active registration flow referencesUSER_MENU) with a hardcodedDIR_RACES "/human"default that now dangles after \S8 movedhuman.lpctounused/. Not fixed -- this file isn't reachable from swmud's actual registration flow (secure/user/sw_body.lpchas its own, completely separate, active implementation), so this is latent, not live.obj/mudlib/newsreader.lpc: uses an undefinedSAVE_OBmacro/ variable pervasively (27 sites). Confirmed viadiffto be byte- identical to Lima's own copy of this file, and Lima's own headers *also* don't defineSAVE_OB-- this is a pre-existing upstream Lima bug, not something swmud or this port introduced, and newsreader isn't part of the preload chain or core verification path. Not fixed (out of scope: this port is responsible for swmud's own changes, not auditing all of Lima's dependencies for latent bugs beyond what swmud itself needs to work).daemons/imud/finger.lpc,contrib/marriage/finger_d.lpc,WWW/cgi/who.lpc: referenceclass fingermembers (visname,level,nickname) that don't exist instd/classes/finger.lpc's actual field list. Intermud finger-protocol and acontrib/-flagged optional marriage extension respectively -- neither is preloaded or part of core gameplay. Not fixed (same category as Lima's own documentedcontrib/marriagespouse-member gap, seelibs/lima/ NOTES.md).secure/daemons/ftp_d.lpc: "Illegal to use local variable in functional" -- the exact same pre-existing Lima-base driver-dialect gap already documented (and left unfixed) inlibs/lima/NOTES.md;ftp_disn't in this archive's preload list either.
⚠️ Real outbound network connection at boot (Intermud-3)
Unlike almost every other lib in this corpus (all sandboxed, no outbound
connections -- see AGENTS.md \S1.3c/\S7.6), daemons/imud_d.lpc
preloads at boot and makes a genuine outbound socket connection to the
public Intermud-3 router network. imud_d.lpc's create() has a
protective check that refuses to load if ADMIN_EMAIL is still Lima's
placeholder "[email protected]" -- exactly the guard that made
libs/lima/'s own imud_d refuse to load (see libs/lima/NOTES.md).
swmud's include/config.h sets ADMIN_EMAIL to a real-looking value
("[email protected]"), so that guard does not trigger here:
create() proceeds to call trigger_reconnect("router")
unconditionally at every boot, same as libs/imud/'s intentional demo
behavior (see libs/imud/NOTES.md). This means this lib should not be
swept into high-frequency automated re-boot loops (round-two/round-
three-style re-test cron, lpcc_check.sh-adjacent live-boot sweeps) the
way the rest of this project's sandboxed corpus safely can be -- each
boot is a real network event against a real third party.
Admin account
Bootstrapped through the mudlib's own real first-boot logic (not a
save-file hand-edit): registered fluffos/Mud@2026 as the very first
account on a completely clean data/{links,players,pshells,wshells}
tree, which sw_body_handle_new_logon() auto-promotes to admin/wizard
per Lima's own convention (see \S5 above for the crash this triggered
and its fix). Completed full Character Creation (Corellian, right-
handed, Rebel alignment) and verified: who shows [Apprentice] Fluffos
the Bantha Fodder (Corellian) with Role Admin Wizard; update
/std/race/wookiee succeeds (Updated and loaded.); admtool opens and
its wizard-gated priv 1 -> administration submenu (showing [admin]-
tagged options) is reachable. A second, ordinary (non-wizard) test
account (testplayer, Wookiee, Imperial) was also registered end-to-end
to confirm the bootstrap-specific fixes above don't regress the normal
player path.
Verification record
scripts/mudclient.py-equivalent raw Python socket sessions through the
real ~/src/fluffos-lima/build-debug/src/driver, multiple independent
boots across the debugging process above: full registration (username,
"is this correct?" confirmation, password+confirm, gender, email, real
name, homepage) -> race selection (verified against corellian and
wookiee, both non-human and human-ethnicity races) -> point-buy
attribute allocation -> dominant hand -> team alignment -> lands in Void
with a starting body -> look (room description + exits correct) ->
score (race/gender/guild/XP/HP/credits all correct) -> who (roster
line with role tag, race, location) -> inventory -> admin update/
admtool (bootstrap-admin account only) -> quit (clean disconnect
back to the User Menu, debug.log free of new errors). No crashes,
zero silent failures, across all of the above after the fixes in this
document.
wasm_status 审计(2026-09-01):内容在专用 WASM 驱动上完全可玩、但与 lima 同样卡在站点基础设施上,结论 noboot
meta.json 的 wasm_status 此前一直留空(README 的 Status 一节写
"WASM status: not attempted")。本次批量审计(见
[[project_wasm_status_audit]])补上这一步,结论直接参照本收藏
libs/lima(164)自己 2026-09-01 那次审计的先例——见
libs/lima/NOTES.md 的「wasm_status 审计」一节。
复用 lima 那次审计已经建好的专用 WASM 驱动
(~/src/fluffos-lima/build-wasm/src/{fluffos.js,fluffos.wasm},
NO_ADD_ACTION/NO_WIZARDS/NO_LIGHT 定义、OLD_ED/PACKAGE_UIDS
未定义,与本 lib 的 README.md/config.fluffos 一贯记载的驱动
要求完全一致,不需要重新编译)。第一次起跑就命中和 lima 自己
secure/simul_efun/misc.lpc 一模一样的 bug:swmud 自己独立重写过
的同名文件(secure/simul_efun/misc.lpc,与 lima 原版逐行对比
差异很大,是 swmud 自己的版本,不是继承 lima 的)里
dump_socket_status() 同样无条件调用 socket_status(),WASM 构建
默认不带 sockets 包,导致 secure/simul_efun 整个编译失败,驱动
拒绝启动。用 lima 已验证过的同一手法修复(#ifdef
__PACKAGE_SOCKETS__ 包一层,退化返回空字符串)。
修复后完整验证:fluffos_boot 成功,登入菜单正常显示"Welcome to
Star Wars MUD!",走完 new name → 确认 → 密码×2 → 性别 → 邮箱/
真实姓名/主页(可跳过)→ 种族选择列表正常显示 13 个种族选项,全程
无未捕获错误——这个 lib 的内容本身在专用 WASM 驱动上是完全可玩
的,obj/secure/socket.lpc/secure/daemons/ftp_d.lpc/
daemons/imud/finger.lpc 等几个非 simul_efun 级的外围文件编译
失败只是正常的预载跳过,不影响真实登入。
但和 lima 一样卡在同一个站点基础设施缺口上:这个项目的站点打包
管线(write_play_page.sh/build_site.sh)给所有 lib 共用
同一份 WASM 驱动二进制,没有任何按 lib 切换驱动配置的机制——部署
到线上时,swmud 仍然会撞上和用共享驱动跑原生版一模一样的"驱动
配置不匹配"问题(NO_ADD_ACTION/PACKAGE_UIDS 等宏的差异会导致
mudlib 自身的启动期检查失败)。标记 playable 会误导站点实际能
跑什么,因此和 lima 一样定为 noboot——这是站点基础设施层面的
缺口,不是这个 lib 自身内容的问题,等以后站点支持按 lib 覆盖驱动
时可以直接翻正,不需要重新调查。
站点基础设施缺口已补上(2026-09-02/03):wasm_status 翻正为 playable
见 libs/lima/NOTES.md"站点基础设施缺口已补上"一节——write_play_page.sh/
build_site.sh 加了 per-lib 自定义驱动目录支持,lima/swmud
共用同一份已提交的驱动产物(scripts/custom_drivers/lima_swmud/)。
本地范围内测试站点(只打包这两个 lib)用 Playwright 通过真实 #cmd
输入框验证:fluffos_boot 成功,"Welcome to Star Wars MUD!" 正常
显示,走完 new name → 确认 → 密码×2,控制台无 JS 报错——和本节
前面用 wasm_client.js 跑通的结果一致。meta.json 的 wasm_status
从 noboot 改为 playable。
Deep functional test (first full §10.7 pass, 2026-09-03)
First continuous playthrough. Prior work was onboarding + the WASM
driver-override flip — never a §10.7 pass. Admin fluffos/Mud@2026
against ~/src/fluffos-lima/build-debug. Unique world content still
does not exist (/d/coru/main absent; players land in /d/common/void).
Tested Void, the lima leftover Monster_Room guild-guard path, quit →
user-menu → re-enter, and a brief combat attempt.
Bug 1: leftover debug writes on every move
std/modules/m_smartmove.lpc::move_to() printed
The destination is a string. / The destination is an object. on
every move attempt. Lima's copy of this module does not have those
writes — they are swmud debug leftovers. out from Void (the only
exit, pointed at the missing START) then correctly says
Construction blocks your path. Verified on a fresh driver after
removing the two write()s: only the construction message remains.
Bug 2: lima §10.7 guild-guard / GUILD_D fixes never reached this overlay
swmud's work/ was copied from lima *before* lima's 2026-08-27 §10.7
pass, so std/guild_guard.lpc and daemons/guild_d.lpc still had the
unguarded query_guild_allies() and the get_dir()-returns-0
load_missions()/load_favors() crash. Ported lima's two guards.
On this lib that was not enough: swmud's std/body.lpc does not
inherit body/guilds (lima does, under USE_GUILDS), so
guilds_belong() is a missing apply and returns 0.
0 & ({}) then threw *Bad argument 2 to &. Added an arrayp()
guard. Verified live: goto /domains/std/Monster_Room → north
now prints the intended block
(The a guard pushes you back. "Guild members only", she growls.)
instead of the go-verb parse crash. Caught Non-existant guild -
sorcery. still lands in /log/catch (same mudlib error handler : 1
visibility lima documented — not a new leak).
Bug 3: user-menu s/p after quit crashed (single-body vs multi-body API)
swmud's secure/user.lpc is the older single-body_fname vintage and
does not inherit user/bodies (lima does; inheriting it here would
nomask-collide on set_body_fname). Lima's usermenu still calls
query_bodies() / query_selected_body() / set_selected_body() /
enter_game(name, fname).
Before the shim: s was *Bad argument 1 to keys() (query_bodies()
returned 0); after a first query_bodies stub, s hit
*Array index must be positive or zero because n_gen is nosave and
defaults to -1; p was *Bad argument 1 to EFUN call_other() because
enter_game() did not exist on the user object.
Shims on secure/user/sw_body.lpc: present the one body_fname as a
one-entry bodies map (gender clamped to 0..3), plus a varargs
enter_game() that forwards to sw_body_handle_existing_logon(0).
Verified live: quit → s lists [1*] Fluffos → p lands back
in Void with a working prompt.
Observed, not fixed (programming, but needs a careful skill-table read)
kill guard in Monster_Room: repeating *can't find skill unarmed
from std/adversary/skills.lpc (SKILL_D->query_skill("unarmed") is
0). Default unarmed skill_used is "unarmed"
(m_damage_source_body.lpc); formula code and the lima trainer use
"combat/melee/unarmed". This is lima-demo combat on swmud's rewritten
skill table — not invented content to "fix" by adding a skill. Left
documented; a later pass should decide whether to rename the default
or register the short name.
Checklist
- Admin login → Void
look/score(Corellian, Bantha Fodder, 1000 XP) outfrom Void: missing START handled as construction block (no crash)- Guild-guard north: blocked without crashing (after bugs 2)
- Quit → s → p re-entry (after bug 3)
- Combat: attempted; skill-table miss above; no unique SW rooms/NPCs exist to test the real combat/crafting tree
- Shop/economy/death: no unique content to exercise; not claimed tested
Driver killed by exact PID after the pass. Test-session save/log churn
(data/links, data/players, data/daemons/guild.o, data/secure/LOG)
was reverted and not committed.