LPmud 2.4.5

✅ 可玩

lpmud245

更新 d911539 2026-09-11 源码 下载 ZIP

▶ 开始游玩 · Play Now

A pristine, pre-LDMud LPMud 2.4.5 snapshot -- the mudlib distributed with Lars Pensjo's own original LPMud driver line, from right before the LDMud/MudOS fork. A real, playable small world (286 files, hundreds of rooms) rather than an infrastructure sketch: new characters land in the village church (which hides a call-button-summoned elevator behind its west wall) and can explore a green, market road, bank, shops, and an adventurers' guild that runs a real fetch quest -- 'Retrieve the Orc slayer from the evil orc shaman, and give it to Leo' -- pointing players at an orc valley with its own orc-treasure room. A twelve-room forest and a 29-tunnel mine flank the village; a giant's lair, path, and confrontation room house a cloned, aggressive level-15 giant NPC; and the village shore road leads out to an entirely separate 'south' region -- its own self-contained ~49-room forest, 18-room island archipelago, and 30-room shoreline.

README

A pristine, pre-LDMud LPMud 2.4.5 snapshot -- the mudlib distributed with Lars Pensjö's own original LPMud driver line, from the era right before the LDMud/MudOS fork. Genuinely FluffOS/MudOS-compatible: a full driver_hook/H_[A-Z_]+/set_driver_hook grep across the whole archive found zero hits (unlike, say, the Docker Hub ldmuddev/lp245 image, which is an LDMud-ported build of the same nominal version). obj/master.lpc's own header comment dates it precisely: "This is the LPmud master object, used from version 3.0... designed to be used with mudlib 2.4.6 or earlier."

This is a real, playable small world -- 286 files, hundreds of real rooms (a village with a church, green, market road, forest, mine, sewers, a maze, a "south" continent, wizard-only areas), NPCs (orcs, wolves, a dragon, guards), a level/experience system, and the classic LPMud spell/combat mechanics -- not a thin infrastructure sketch like the already-onboarded basis.

Provenance

Recovered directly from the still-live ftp.lysator.liu.se LPMud archive mirror (https://ftp.lysator.liu.se/pub/lpmud/mudlibs/other/2.4.5.tar.gz), same as basis -- no Wayback Machine recovery was actually needed, the file is still served as-is.

Highlights (see NOTES.md for full detail)

Registration flow

Type your name -> (new character) password -> confirm password -> email address (or none) -> gender (m/f/o) -> straight into room/church, the starting room.

Local play

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

Port 40262.

NOTES · 移植与修复记录

LPmud 2.4.5 -- porting notes

Source: other/2.4.5.tar.gz, recovered directly from the still-live ftp.lysator.liu.se LPMud archive mirror (https://ftp.lysator.liu.se/pub/lpmud/mudlibs/other/2.4.5.tar.gz). Slug lpmud245, number 960, port 40262. 582 raw files (286 .c sources), mudlib root at the archive's own top level. No driver_hook/ set_driver_hook/H_[A-Z_]+ usage anywhere (confirmed by grep) -- genuinely a pre-LDMud, MudOS-line-compatible snapshot, unlike the LDMud-ported Docker Hub ldmuddev/lp245 image of nominally the same version. obj/master.lpc's own header comment: "This is the LPmud master object, used from version 3.0... designed to be used with mudlib 2.4.6 or earlier."

1. Extraction and conversion

Pure ASCII/English archive, 0 lossy conversions. 286 files renamed .c->.lpc, 5 literal .c" references fixed, 8 files static->nosave.

2. Proactive on-sight checklist findings

3. Compile-time / boot-time driver-compat fixes

4. Compile-sweep triage: known-acceptable remaining failures (3 of 286)

5. Live playthrough (native driver)

Full flow verified in one continuous session, port 40262: fresh registration (name / password twice / email none / gender) reaching room/church -> look (correct room description, all objects mentioned) -> south (moves to room/vill_green, correct room description including "There are three obvious exits: north, west and east" -- the exact code path the room/room.lpc recursion bug above broke) -> look again (correct) -> score (correct XP/gold/HP/ spell-points/age display) -> quit (clean save + disconnect). Tested with both m/f gender selections. Re-login (existing-password path) verified separately: password accepted, correct room reached, movement and score both still correct. debug.log fully clean (zero error lines) across every test session after all fixes above.

6. WASM

Boots and plays identically under the WASM build (~/src/fluffos/build-wasm/src, via scripts/wasm_client.js): full registration -> look -> quit, correct output throughout. wasm_status: playable.

7. New AGENTS.md catalog entries added this session

(Alongside the basis-onboarding entries for the closure/function- pointer gap, new/class reserved words, and the extract/ log_file/privp/cat missing-efun list.)

1. file_name() always returns a leading / on this driver -- any archive comparing file_name(ob) == "bare/path" (no leading slash) against a literal path constant will silently ALWAYS be false. Watch for this specifically in "am I my own shared singleton instance" self-identity checks, where a false negative causes infinite self-delegation (a "Too deep recursion" crash) -- as opposed to the more common case of just silently failing to match, which tends to surface as a missing-feature symptom instead of a crash. 2. A non-wizard player's visible error output can be a complete red herring when mudlib error handler is on (the default): this driver replaces the real error text with the configured default error message for any non-wizard command_giver, while still logging the FULL real error (including a complete stack trace) to debug.log every time, unconditionally. A crash whose player-facing symptom looks like ordinary (if terse) game content -- not an obvious error message -- should still prompt a direct debug.log read before concluding "no bug here." This generalizes AGENTS.md §10.3's existing point about logon() swallowing errors to a much broader, config-driven case that can apply to literally any command. 3. command(str, ob) (run a command as a specific, non-current object) is not supported on this driver at all -- command(str) always runs against current_object, never command_giver/ this_player(). Needs the same per-target do_command()-wrapper treatment as move_object()'s 2-arg dialect gap (§7.158). 4. transfer(item, dest) -- a second classic MudOS efun for the same "move an arbitrary object" concept move_object() also covers on old drivers; not real on this driver either. Fix identically: A->move_object(B) via the same per-object shim. 5. add_action("fun"); add_verb("cmd"); -- a two-statement legacy idiom for what modern add_action(fun, cmd) (2-arg, both required on this driver) does in one call. Mechanically mergeable via a regex over adjacent statement pairs. 6. creator_file() is required by this driver's PACKAGE_UIDS build for literally every object load, not just at boot like get_root_uid()/get_bb_uid() (§7.2's existing entry) -- creator_file() deserves its own line in that catalog entry since its absence blocks ALL subsequent loading, not just initial boot.

8. §10.7 deep functional test (2026-08-31)

Full continuous-session playthrough on the native driver (port 40262): fresh registration -> walked the ENTIRE village crossroads area (church -> vill_green -> vill_track -> vill_road1 -> vill_road2 -> shop -> adv_guild -> yard) rather than just the two rooms §5's original pass covered, tested the shop's list/buy/value commands, the guild's list/cost/advance commands, a real multi-round combat against the yard's Beggar NPC (hit/miss/damage messages both directions, correct HP tracking), quit mid-combat, and a fresh reconnect (password accepted, HP correctly persisted at the damaged value, room reset to the starting room/church matching this lib's existing documented save-data scope). Also ran a 200s WASM scripts/wasm_boot_watch.sh lpmud245 200 long-sit.

Severe bug found and fixed: ~80% of the whole game world (70 of 88

rooms) started dark and/or completely exit-less on every fresh boot, for up to 30 minutes, because the create() { reset(0); } fix already applied by hand to a handful of custom rooms (§3's room/church.lpc writeup) was never extended to the two shared macro headers (room/room.h's ONE_EXIT/TWO_EXIT/THREE_EXIT/FOUR_EXIT and room/std.h's identically-named but independent macro set) that generate the vast majority of this archive's actual room files

Found by simply continuing the walk past where §5's original pass stopped: south from the church into room/vill_green worked exactly as documented, but the very next room east (room/vill_track, one hop from spawn) printed "A dark room.", look said "It is too dark.", and every direction command including the one that had just been used to enter the room returned "What?" -- a genuine dead-end softlock for any new player who wandered one room past the tested path, not a cosmetic darkness issue.

Root cause: this whole archive uses the classic reset(arg){ if (!arg) {...} } idiom as its room constructor (exits, light, and descriptions are all populated inside reset(), only on the very first, arg==0 call) -- but this driver's call_create() always marks a freshly-loaded object as "already reset" and defers ITS real first reset() call for up to "time to reset" seconds (room/ church.lpc's own extensive comment, §3, already documents this exactly). church.lpc (and a handful of other hand-written rooms: bankroom, elevator, wiz_hall) got an explicit create() { reset(0); } added individually to force synchronous initialization -- but this archive's OTHER 88 room files are almost all generated by one of two near-identical macro-header systems (room/room.h, inherited via #include "room.h" + inherit "room/room", used by 68 files; room/std.h, a fully standalone macro set with no inheritance, used by 13 files, 4 of which -- including church.lpc itself -- override the macro entirely with hand-written code and already had the fix). Neither macro header itself was ever given the create() fix, so every room instantiated purely by invoking ONE_EXIT(...)/ TWO_EXIT(...)/etc. (which is the OVERWHELMING MAJORITY of the explorable map: every forest*/plane*/eastroad*/giant_* room, plus the shop, the bank, and the adventurers guild) never ran its reset() until the driver's own lazy scheduler eventually got to it.

The two macro systems differ in how bad the resulting symptom is:

Fix: added create() { reset(0); } directly inside each of the 8 macro definitions (4 in room/room.h, 4 in room/std.h) rather than hand-editing 81 individual room files -- confirmed no macro-generated file already defines its own create() (would be a duplicate-function compile error) and no already-fixed hand-written file (church, bankroom, elevator, wiz_hall) invokes either macro. Verified live, post-fix: room/vill_track is lit with both exits working on the very first visit after a fresh boot; room/shop and room/adv_guild are fully described (list/buy/cost/advance all producing correct output) on first entry too. New AGENTS.md catalog entry, §7.185 (this is a coverage gap in an ALREADY-catalogued fix pattern -- §3's own writeup already explains the underlying mechanism correctly -- rather than a new root cause, but the specific "a shared macro header used by the vast majority of content files was missed by a fix applied file-by-file to only the hand-written exceptions" shape is worth its own entry so a future sweep checks macro headers first).

Confirmed NOT a bug -- one remaining gap, low priority, left alone

obj/quicktyper.lpc (a heartbeat-driven wizard debug/auto-typer utility, not player-facing content) is the ONLY file under obj// players/ still missing its own create() fix (every other file in those trees already has one, confirming this archive's original onboarding pass thoroughly covered obj/ by hand -- the miss was specifically the two room macro headers, not a general gap). Its reset() only sets an owner name and allocates a history array for its own debug/logging use, both of which the driver's own eventual lazy reset (or the object's own later use) still populate correctly before they matter; no observed player-facing symptom. Not fixed, noted here for completeness.

Regression check

Full re-walk of the fixed rooms plus every other already-verified command (score, inventory, combat, quit, reconnect) in one final continuous session: zero errors in the driver's own captured stdout (this native build's debug.log is dead for the process's whole life per AGENTS.md §10.9, so stdout is the only reliable error channel).