Commit graph

14 commits

Author SHA1 Message Date
Stephen Dennis
bd86caaba0 nls: one msgid per sentence for the home/dropto change messages (#1419)
Folded in from review.  create.cpp built two sentences out of three M_()
fragments each:

    "Home of %s(#%d) changed from "  +  "%s(#%d) to "  +  "%s(#%d)."

Three catalogue entries for one sentence is worse than leaving it unmarked,
because it looks translated while making the sentence permanently
untranslatable:

  * clause order is frozen -- a translator cannot move "changed from"
    relative to the subject, and languages that invert from/to or put the
    verb last cannot express it at all;
  * the trailing spaces are load-bearing and invisible in a PO editor, so
    dropping one runs the sentence together with nothing to catch it;
  * "%s(#%d) to " is not a sentence in any language and gives the translator
    no context for what "to" joins;
  * "%s(#%d)." and "%s(#%d) to " were shared between the home and dropto
    sites, so one translation had to serve both.

Whole sentences are the point of the Phase 3 slices -- #1568's own summary
gives "makes whole sentences untranslatable as a unit" as the reason for
allowing formats at all.

Now one format each, six conversions, and the LBuf/safe_str assembly goes
away with them.

Output is unchanged; verified against a throwaway game:

    Home of Thing(#3) changed from Limbo(#0) to Limbo(#0).

test-nls 570 msgids clean (down from 572: three fragments became one, twice,
and two of the fragments were shared).  test-format 31744 assertions pass.
Catalogue rebuilt through `make -C mux/po mo`, which now carries msgfmt -c.
Suite 1553 passed / 0 failed / 319 of 319.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 09:28:27 -06:00
Stephen Dennis
9703d8c104 nls: format-string slices for create, set, and wiz (#1419)
Continue Phase 3 after the rob slice: mark player/staff tprintf,
mux_sprintf, and raw_broadcast format templates with M_() so whole
sentences like "%s created as room #%d." enter the catalogue.

Left as T(): softcode machine templates ("#%d") and the ANSI color
assembly ("%s%s%s") — not notify prose. Log-only "Strange object type"
stays T() as well.

Regenerate pot/xx/mo without fuzzy entries. Format and NLS guards green.
2026-07-27 15:04:54 +00:00
Stephen Dennis
b5ee3b6f81 refactor: use UTF-8 text in user-facing string literals (#1513)
Replace ~900 typographic \xE2\x80\x.. escapes (curly quotes, en dashes)
and a few \xE2\x80\230 octal workarounds with real UTF-8 in message
strings under mux/modules and mux/src. Leave stringutil and convert
charset mapping tables as explicit byte sequences.
2026-07-26 21:52:48 -06:00
Stephen Dennis
f3b6388fa8 nls: mark create/quota notify prose with M_ (#1474)
Phase 2b first slice: whole-sentence notify/notify_quiet messages in
create.cpp and quota.cpp (not tprintf formats). Regenerates tinymux.pot
and expands the xx pseudo-locale so LANGUAGE=xx can exercise the new
strings. Smoke suite stays English under LANG=C.
2026-07-26 19:44:01 -06:00
Stephen Dennis
e7eb6ec76d nls: route literal #-1 softcode tokens through S_ (#1475)
Mechanical hygiene under the opt-in M_() design: replace T("#-1…") and
T("#-2…") with S_() so softcode ABI tokens are obvious in source and
cannot enter a player catalog. ~400 call sites across engine, exp3,
mail, and driver. Assembled/library-spliced diagnostics (plan §4.2)
are unchanged where they are not a single literal.
2026-07-27 01:00:55 +00:00
Stephen Dennis
2f106f200f fix(win32): migrate the remaining mux_atol callers to mux_atoi64 (#1373)
Completes the sweep the issue called for.  mux_atol returns long, which
is 32-bit on LLP64, so every caller silently truncated on Windows.  Two
of those were real defects (the truthiness family and cf_size, fixed in
the preceding commits); the rest were latent, waiting for a value large
enough to matter.

Rather than audit 290 sites for whether each can reach 2^31 today, use
the 64-bit parser everywhere and remove the class.  A dbref cannot
overflow now, but nothing stops a later caller passing that same site a
timestamp or a byte count.

Pure 1:1 substitution: 285 lines changed, and every removed line
contained mux_atol while every added line contains mux_atoi64.  No
control flow, no types, no behaviour beyond the wider parse.

This is a NO-OP on LP64 -- long is already 64-bit on Linux and macOS, so
the generated code there is unchanged.  It only widens the parse on
Windows.  Narrowing destinations are unaffected either way: `int x =
mux_atoi64(s)` truncates exactly as `int x = mux_atol(s)` did, on both
models.

Left alone: mux_atol itself in mathutil, its declaration, and three
comments that name it.  Callers that genuinely want 32-bit semantics can
still ask for them; none appear to.

Verified on Windows: full solution builds clean with no new warnings,
smoke is 1418 passed / 16 failed / 0 crashes / 306 of 306 dispatched --
identical to before the sweep, with the same 16 build-configuration
failures (exp3 module not loaded, hmac/digest behind UNIX_DIGEST).
Spot checks after the change: the boolean family returns 1 for multiples
of 2^32, cf_size round-trips 3000000000 and still reads -1 as unlimited,
and arithmetic, string and list functions are unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 10:12:35 -06:00
Stephen Dennis
c33fa62213 fix(object): harden create freelist, purge_going, and reverse @open
- #1185: zero Powers/Powers2 on create_obj; require zero powers in IS_CLEAN
  so freelist recycle cannot inherit privilege from corrupt garbage slots
- #1183: validate A_DESTROYER with Good_owner before destroy_player/chown_all;
  fall back to GOD and log when the attribute is stale or corrupt
- #1188: refuse reverse @open when the destination is HOME with an explicit
  message instead of a silent open_exit bail
2026-07-25 11:09:32 -06:00
Stephen Dennis
857c22274c fix(create): @clone/preserve re-links without ownership steal (#1181)
Under CLONE_PRESERVE, set exit destination / room dropto directly instead
of calling link_exit(), which charged open cost, transferred ownership to
the wizard executor, and HALTed the clone.
2026-07-25 08:15:17 -06:00
Stephen Dennis
fcae41511b Fix command-side verb correctness bugs (@clone, @ps, whisper, @flag, @mark)
Correctness sweep of the command-side verb handlers. Five confirmed bugs
plus a help-text correction, verified by dual-lens review and code reading
(the read-only smoke harness can't exercise these verbs directly):

 - @clone/cost on an exit bypassed the "must control current location"
   check (it lived only on the non-/cost path), letting a builder splice a
   cloned exit into a room they do not control. (#855)
 - The @mark/@mark_all/@apply_marked DB-cleaning refusal cited @unmark_all,
   which does not exist (produces "Huh?"); corrected to @mark_all/clear.
   (#856)
 - @ps <object> reported nothing for a controlled object owned by another
   player; do_ps was missing the non-player-target else clause that the
   sibling @halt has (clear the owner filter). (#857)
 - whisper "<quoted name>" skipped the locality/connected gate the unquoted
   form applies, giving a success confirmation plus a delivery error and
   polluting A_LASTWHISPER; also fixed an adjacent quoted-name continue that
   did not advance the parser. (#858)
 - @flag/remove of an unknown/empty flag name was silent; now reports an
   error like the other flag-name failure paths. (#859)
 - report help said 8-hour segments but the code uses 4 (deliberately, per
   4a845139f); corrected the help. (#860)

Also restores the "## JIT / DBT Engine" CHANGES heading dropped during an
earlier 2.14.0.8 edit. Build clean, all 1264 smoke tests still pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 06:29:11 -06:00
Stephen Dennis
87485bc401 Migrate 22 alloc_lbuf/free_lbuf sites to LBuf RAII
Replace manual alloc_lbuf/free_lbuf pairs with LBuf RAII wrappers
in 12 engine source files: rob, walk, quota, wiz, session, object,
log, match, move, create, flags, boolexp.  This eliminates ~40
explicit free_lbuf calls on error paths that are now handled by
destructors, removing leak risk in early-return and multi-exit
functions (boolexp alone had 13 exit-path frees across two
functions).  Buffers returned by atr_get/atr_pget or to callers
are left manual since LBuf cannot adopt externally-allocated
buffers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:46:22 -06:00
Stephen Dennis
82d0ff1728 Fix Phase 1 routing correctness gaps 2026-03-29 03:28:10 -06:00
Stephen Dennis
a348e27f33 Implement Phase 1 routing: static unconditional next-hop tables
Add route() softcode function with BFS-based shortest-path routing
over rooms marked NAVIGABLE. The routing table stores only the next-hop
exit for each (source, dest) pair, compressed via diagonal elimination,
adjacent marking, and row redundancy. Lazy rebuild on generation-counter
mismatch triggered by topology changes (@dig, @destroy, @link, @open,
@unlink) and NAVIGABLE flag changes. SQLite schema v10 adds route_nodes,
route_table, route_meta tables for future persistence phases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 03:18:37 -06:00
Stephen Dennis
0b28265577 Remove dead code: LogStatBuf() and GAME_DOOFERMUX
LogStatBuf() was defined but never called. GAME_DOOFERMUX was never
defined, making all four #ifdef blocks dead code (A_REGINFO attribute,
RegInfo table entry, registration stamp on player create, and alternate
execl argv[0]). Update smoke test expectations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 02:07:41 -06:00
Stephen Dennis
4ff1398de1 Restructure mux/ directory: component-based layout with proper build root
Move from flat mux/src/ layout to clean component hierarchy:
- mux/ is now the autoconf/automake build root (configure.ac lives here)
- mux/include/ — shared headers used by multiple components
- mux/lib/ — libmux.so (core utilities, no game state)
- mux/src/ — netmux driver only (thin networking shell)
- mux/modules/engine/ — engine.so (game logic)
- mux/modules/{comsys,mail,exp3,sqlproxy,sqlslave}/ — external modules
- mux/ganl/ — GANL networking library
- mux/sqlite/ — SQLite amalgamation (builds libsqlite3.a)
- mux/announce/ — announce tool (was mux/src/tools/)

Build changes:
- SUBDIRS ordering: ganl sqlite lib src modules announce
- libmux.so gets -Wl,-soname,libmux.so; netmux links via -L -lmux
- engine.so links libsqlite3.a and libmux.so with -Wl,--no-undefined
- RPATH uses $ORIGIN for portable .so resolution
- Install hooks use absolute paths for game/bin symlinks

Bug fixes:
- engine.so mux_Register() now passes nullptr to mux_RegisterClassObjects
  (matches all other modules; libmux already has the factory via dlsym)
- DbConvert() now calls pcache_init() before db_write, fixing a latent
  crash (free(): invalid pointer) when exporting from SQLite databases

411/411 smoke tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:38:37 -06:00
Renamed from mux/src/create.cpp (Browse further)