Foundation I

✅ 可玩

foundation1

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

▶ 开始游玩 · Play Now

A stripped-down, classic Nightmare-3.3-derived LPC library released by George Reese ("Descartes of Borg") in April 1995 -- a bare engine (login/registration, security, command dispatch, help, mail, message boards, Intermud-3) with no combat, limbs, or stats system at all, meant as a clean base for LPC programmers to build their own game on top of, not a playable-out-of-the-box world. This is the direct, earlier ancestor of this collection's separate `foundation2` (a distinct, more developed later release by the same author) -- not a duplicate. The one shipped starting room is a softly-lit cavern with magic pools, with the real player command set (look/status/inventory/quit and more) fully implemented. An optional teaching content tree references an incompatible room/item API from a different snapshot of this engine and doesn't compile, a pre-existing content mismatch. Like foundation2, this lib makes a real outbound Intermud-3 socket connection at boot (to a near-certainly-defunct 1990s host) and should not be swept into high-frequency automated re-boot loops.

README

A stripped-down, classic Nightmare-3.3-derived LPC library, released by George Reese ("Descartes of Borg") in April 1995. Per its own shipped README: "This LPC library is designed very much for people who know what they are doing. Unlike Nightmare, it does not come with any configuration script to get you started, a combat system for a fantasy MUD, or a starter area." Foundation I is a bare engine (login/ registration, security, command dispatch, help, mail, message boards, Intermud-3) meant as a clean base for LPC programmers to build their own game on top of -- not a playable-out-of-the-box game world.

This is the direct, earlier ancestor of this collection's existing foundation2 (a separate, more developed later release by the same author -- Foundation I's own README says explicitly that its documentation was due to be "customized for Foundation II, due May 15" [1995]). The two are distinct codebases with real, independently-drifted differences (see NOTES.md), not duplicates of each other.

Source: recovered from the MUDBytes File Repository (mudbytes.net, file #1043) via the Wayback Machine, since the live download endpoint is gone. Slug foundation1, number 946, port 40248.

Highlights

Registration flow

new name (lowercase letters only, 2-15 chars) -> "Do you really wish <name> to be your name? (y/n)" -> password (5+ letters) -> confirm password -> gender (male/female) -> display name (blank = default) -> email (required, must look like user@host) -> real name (optional, blank OK) -> a news screen (<return> to continue) -> lands in the Standard domain's starting cavern.

There is no score command anywhere in this minimalist archive (matching its own README's "no ... stats system" description) -- status is the closest equivalent, printing hp/sp/mp/experience.

Admin account

Created through the mud's own normal registration flow (not a save-file hand-edit) and granted access by adding it to the existing (SECURE) group entry. See NOTES.md for the exact edit and how it was verified.

Status

Boots clean: zero fatal errors across repeated fresh-driver boots. Verified live with a real driver session and a raw socket client: a brand-new character's full registration, world entry into the Pool Room, and look/status/inventory/quit all producing correct output.

270 of 275 .lpc files pass a full lpcc_check.sh batch compile sweep; the 5 that don't are all non-preloaded, non-boot-critical example/ teaching content with a pre-existing content/API mismatch predating this port (see NOTES.md \S3) -- expected for a deliberately minimal engine like this one, not a sign of missing conversion work.

WASM status: playable. Shared WASM driver. dump_socket_status() in secure/SimulEfun/SimulEfun.lpc is #ifdef __PACKAGE_SOCKETS__ so the eager simul_efun compiles without the sockets package. Admin login (fluffos / Mud@2026) into the Pool Room, plus look / status / quit, verified with scripts/wasm_client.js. Play: https://mudlibs.fluffos.info/foundation1/

Local run

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

Game port: 40248.

NOTES · 移植与修复记录

Foundation I -- porting notes

Source: foundationI_fluffos_v1.zip, recovered from the MUDBytes File Repository (mudbytes.net, file #1043) via the Wayback Machine, since the live mudbytes.net file-download endpoint is gone. The CDX API (https://web.archive.org/cdx/search/cdx?url=mudbytes.net/files/download/1043*&output=json) showed one 200-status snapshot, 20190802021701 (2019-08-02); fetched as https://web.archive.org/web/20190802021701id_/http://mudbytes.net/files/download/1043/ (a 301-redirect snapshot for the bare, non-timestamped URL also exists but resolves to nothing useful directly -- the exact 200 snapshot above is the one that works). Content-verified: 2,329,667 bytes, a valid zip (store compression), 1542 entries, 897 real files under lib/ dated 1994-95. Slug foundation1, number 946, port 40248. The zip bundles a fluffos-2.9-ds2.12 driver source snapshot, plus bin/, win32/, old/ build/install scaffolding -- all ignored, this project uses its own driver. The real mudlib root is the zip's lib/ directory (its own bin/mudos.cfg confirms: mudlib directory : /mud/foundation/lib, master file : /secure/daemon/master). A full-tree grep for driver_hook/set_driver_hook across lib/ returned zero hits, confirming genuine MudOS/FluffOS lineage (not LDMud).

Relationship to foundation2 -- NOT a duplicate

This collection already has an unrelated foundation2 (174, port 40221). Foundation I and Foundation II are both by the same author, George Reese ("Descartes of Borg"), but they are two distinct, independently-shipped releases:

meta.json's duplicate_of is null -- this is treated as its own distinct onboarding target per the task, not folded into foundation2.

1. Conversion

English-language archive (not GBK-encoded) -- scripts/convert_lib.sh against raw/foundationI_fluffos_v1/lib confirmed this: 880/897 files already valid UTF-8, 1 lossy conversion, 16 skipped binaries (compiled .o save files under secure/save//daemon/save/, correctly left alone), 275 files renamed .c->.lpc, 81 literal .c" references fixed, 9 local angle-bracket #includes converted to quotes, 76 files touched by the static->nosave sweep. No stragglers (*.C, unrenamed .c) after conversion.

2. Compile-time driver-compat fixes

- std/user/refs.lpc's set_ref(string ref, ...)/get_ref(string ref) -- this file is inherited straight into the player body class (std/user.lpc via the REFS macro), so this alone broke compilation of the ENTIRE player body. Renamed ref -> refname. - daemon/refs.lpc's parallel set_ref/get_ref/resolv_ref (the daemon-side interface to the above) -- same rename. - secure/daemon/master.lpc's load_access(string cfg, mapping ref) (plus its master.h prototype) -- renamed to refmap.

lpcc_check.sh result after fixes: 270/275 files pass. The remaining 5 are pre-existing content gaps (see \S3), none boot-critical.

3. Pre-existing content gaps (not fixed -- out of driver-compat scope)

4. WASM-era standard patches

5. Live verification

Booted the real native driver (~/src/fluffos/build-debug/src/driver config.fluffos, cd'd into libs/foundation1 first) repeatedly; zero fatal errors, "Accepting telnet connections on 0.0.0.0:40248." / "Initializations complete." every time. Full registration -> world entry -> command verification, via scripts/mudclient.py, one continuous session:

name: wizbaz -> y -> password (Mud@2026) -> confirm -> gender: female ->
display name: <blank, defaults to Wizbaz> -> email: [email protected] ->
real name: <blank, defaults to "Unknown"> -> [news pager: <return>] ->
look -> status -> inventory -> quit

All correct: entered domains/Standard/center (the "Pool Room" -- "You find yourself standing in a large cavern, lit softly by glowing lichen...") with its make_pools()-cloned pool object present, look re-displayed the same room correctly, status (this lib's real score-equivalent -- there is no score command anywhere in this minimalist archive, matching its own README's "no ... stats system" description, \S2.3-style) printed hp: 1/10 sp: 1/10 mp: 1/10 experience: 0, inventory printed You are empty-handed., and quit cleanly printed Please come back another time!. Also verified the name-validation gate (BANISH_D->valid_name() correctly rejects non-lowercase-alphabetic names, e.g. a name containing a digit) and the admin account end-to-end (registration, (SECURE) grant, live _call me;move;/domains/Standard/center returning MOVE_OK (0) plus a correct look afterward). log/errors/* only ever accumulated the harmless nosave-function/prototype-mismatch warnings cataloged in \S3 -- no runtime crash signatures.

Environment note, not a Foundation I bug: in this session's sandbox, a driver launched even with setsid nohup ... & disown (\S10.8's documented workaround for "plain nohup ... & has died from stray SIGTERMs between tool calls") still reliably stopped listening/exited cleanly (no crash trace, no log signature) around the ~100-130 second mark regardless of activity -- reproduced 3 times, including one run where nothing at all was sent to it. Every actual registration/ gameplay verification above completed well inside that window in one continuous client session, so this didn't block verification, but a future session re-testing this lib (or debugging via a long-sit \S10.0 boot-watch) should budget for restarting the driver more often than usual and not read a disappearance alone as a Foundation I-side crash without also checking whether the process merely aged out of this particular sandbox's process lifetime.

WASM status: not attempted this session (wasm_status left "").

深度功能测试 / §10.7 deep functional test (2026-08-31)

Round-two pass per the queue directive to hold every recently-onboarded lib to the §10.7 bar. Since this lib has no combat/skills/stats system (confirmed in \S1-5 above, matching its own README), this pass targeted the actual engine features onboarding hadn't yet exercised: mail, help, bug reports, finger, and a real quit/reconnect cycle. Booted ~/src/fluffos/build-debug/src/driver config.fluffos from libs/foundation1/, tested via scripts/tmux_mud.sh (two concurrent sessions, fluffos the seeded admin and a fresh throwaway mortal xiaoyan), restarting the driver as needed for this sandbox's documented ~100-130s lifetime quirk (\S5) and to pick up each fix.

Bugs found and fixed

All of the following share ONE root cause, a single systemic pattern — see the new AGENTS.md \S8.23 entry for the full writeup and confirmed recurrence in the nightmare3 sibling lib:

A (: "funcname" :) single-string functional literal was valid MudOS syntax in 1993-95 (this lib's own doc/lpc/types/function states it verbatim: "makes a function pair that is equivalent to (: this_object(), "funcname" :)"), but this driver's compiler no longer honors that — calling such a "function" just returns the string, the named function is never invoked. This silently broke every edit()/more() "when you're done, call me back" hook written that way:

Left unfixed, judged low-impact: secure/std/post.lpc:34-36's set_prevent_get/drop/put( (: "remove"/"drop" :) ) are the SAME broken construct, but the caller (std/Object.lpc's allow_get()) only checks the callback's return value for TRUTHINESS — a string is truthy regardless of content — so the intended "block this action" behavior still works correctly; only the descriptive denial message is silently dropped. The affected object (the postal mailbox) is also set_invis(1) so a player can't normally target it with get/drop/put at all, making this a barely-reachable cosmetic gap. Left as-is per this lib's own existing NOTES.md precedent for similarly low-impact cosmetic nosave/warning-only issues.

A separate, unrelated bug found via finger

secure/daemon/finger.lpc's user_finger_display() had a missing-braces bug: if(this_player() && adminp(this_player())) if(...) tmp = ...; else tmp = ...; drow = tmp; — the trailing drow = tmp; was written as if it were inside the outer if, but with no braces it's an UNCONDITIONAL statement that runs for EVERY finger, admin viewer or not. Live repro: finger fluffos as the non-admin xiaoyan printed Male IdeaExchanger Coder of the HackersOn since : ... — missing the title line entirely AND missing the newline before "On since", because drow got silently reset to the stale, newline-less tmp value from several lines earlier instead of keeping the properly-built (title + bio + trailing \n) string. Fixed by adding braces around the admin-only email-line block (line ~47-52) so drow = tmp; only executes when actually appending the email line for an admin viewer. Verified fixed: finger fluffos as xiaoyan now correctly prints the title line, the bio line, "Last on: ..." (or "On since : ..." if actively connected), unread-mail count, and "No Plan." each on its own line.

Confirmed working (no fix needed)

Observed but NOT fixed — flagged for the record, not a clear bug

log/runtime accumulated several thousand *Denied write permission in save_object(). entries this session, all from daemon/intermud.lpc's eventRead() (lines ~121/145, save_object(SAVE_INTERMUD) after a startup-reply/mudlist packet) via secure/std/client.lpc's eventReadCallback. Two things both need a human's attention but neither felt safe to "fix" under this pass's driver-API-misuse-only scope: (1) the daemon apparently can NEVER persist its Intermud mudlist/nameserver state under this lib's directory-privs security model (a real functional gap, but fixing it means deciding how a system daemon should be granted write access under this lib's own custom, install-it-yourself privs scheme — a security-design judgment call, not a clear typo); (2) the sheer VOLUME of packets received in a ~20-minute session (thousands) from the hardcoded 1996 nameserver address is surprising and not something the LPC code controls either way (no crash or unbounded growth observed, just a lot of log noise) — flagged as an environment/network observation, not a lib bug.

Flagged unverified

WASM measurement (2026-09-03)

meta.json was already playable from the 2026-08-31 deploy-unblock (2ec643a7c45); the README still said "not attempted." Cold-boot under the shared ~/src/fluffos/build-wasm failed on the eager simul_efun calling socket_status() from dump_socket_status() in secure/SimulEfun/SimulEfun.lpc — same lima §1.3(c) / wilderness class. Guarded the body with #ifdef __PACKAGE_SOCKETS__ (empty-string stub otherwise). After that, scripts/wasm_client.js logged in as fluffos / Mud@2026 into the Pool Room cavern, look showed lichen, status reported hp: 1/10, and quit printed "Please come back another time!" Shop/combat/death were not exercised this pass.

Shop + 拜师 (2026-09-04 librarian slice)

Content-absent, not a programming bug. This is the 1995 "minimalist LPC Library" snapshot: no combat, no stats, no currency, no vendor objects, and no apprentice/guild verbs. secure/etc/shops is leftover Nightmare path list (/d/standard/supply.c, wizard cartesia/winona shops) — none of those rooms exist in this archive (zero *shop* / *supply* under work/, no do_buy/cmd_buy). Live on 40248 as seeded admin fluffos / Mud@2026 into the Pool Room cavern: buy torch, list, shop, and apprentice all printed What?. Help's player-general topics are mail/prompt/terminal — no shop. Left as-is.