@maka/maka-cli 5.73.0 → 5.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/_index.d.ts +0 -4
  3. package/bundle/typescript/src/commands/game/_index.js +6 -5
  4. package/bundle/typescript/src/commands/game/_index.js.map +1 -1
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js +6 -6
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js.map +1 -1
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.d.ts +2 -0
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +26 -7
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +29 -2
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +10 -5
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js.map +1 -1
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/move.d.ts +42 -0
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js +288 -46
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js.map +1 -1
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js +8 -0
  18. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js.map +1 -1
  19. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +20 -15
  20. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
  21. package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js +8 -1
  22. package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js.map +1 -1
  23. package/bundle/typescript/src/commands/game/sideQuest/commands/sustain.d.ts +48 -0
  24. package/bundle/typescript/src/commands/game/sideQuest/commands/sustain.js +135 -0
  25. package/bundle/typescript/src/commands/game/sideQuest/commands/sustain.js.map +1 -0
  26. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +10 -2
  27. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
  28. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js +9 -8
  29. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js.map +1 -1
  30. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.d.ts +83 -0
  31. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js +253 -0
  32. package/bundle/typescript/src/commands/game/sideQuest/factories/chargen-factory.js.map +1 -0
  33. package/bundle/typescript/src/commands/game/sideQuest/factories/repro-scene.js +116 -3
  34. package/bundle/typescript/src/commands/game/sideQuest/factories/repro-scene.js.map +1 -1
  35. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +3 -0
  36. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
  37. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +21 -1
  38. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js.map +1 -1
  39. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +61 -0
  40. package/bundle/typescript/src/commands/game/sideQuest/game.js +146 -23
  41. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  42. package/bundle/typescript/src/commands/game/sideQuest/headless.js +48 -5
  43. package/bundle/typescript/src/commands/game/sideQuest/headless.js.map +1 -1
  44. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +35 -0
  45. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +46 -0
  46. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  47. package/bundle/typescript/src/commands/game/sideQuest/types/repro.d.ts +158 -3
  48. package/bundle/typescript/src/commands/game/sideQuest/types/repro.js +24 -1
  49. package/bundle/typescript/src/commands/game/sideQuest/types/repro.js.map +1 -1
  50. package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +33 -3
  51. package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js.map +1 -1
  52. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-dump.js +8 -8
  53. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-dump.js.map +1 -1
  54. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-vocab.d.ts +4 -2
  55. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-vocab.js +15 -3
  56. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-vocab.js.map +1 -1
  57. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.d.ts +6 -0
  58. package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.js.map +1 -1
  59. package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.d.ts +24 -0
  60. package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js +31 -0
  61. package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js.map +1 -1
  62. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-names.d.ts +63 -0
  63. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-names.js +104 -0
  64. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-names.js.map +1 -0
  65. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +4 -3
  66. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js.map +1 -1
  67. package/bundle/typescript/src/commands/game/sideQuest/utilities/identity.d.ts +26 -0
  68. package/bundle/typescript/src/commands/game/sideQuest/utilities/identity.js +37 -0
  69. package/bundle/typescript/src/commands/game/sideQuest/utilities/identity.js.map +1 -1
  70. package/bundle/typescript/src/commands/game/sideQuest/utilities/map-view.d.ts +19 -0
  71. package/bundle/typescript/src/commands/game/sideQuest/utilities/map-view.js +22 -0
  72. package/bundle/typescript/src/commands/game/sideQuest/utilities/map-view.js.map +1 -1
  73. package/bundle/typescript/src/commands/game/sideQuest/utilities/marks.js +2 -1
  74. package/bundle/typescript/src/commands/game/sideQuest/utilities/marks.js.map +1 -1
  75. package/bundle/typescript/src/commands/game/sideQuest/utilities/repro-launch.d.ts +1 -1
  76. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.d.ts +71 -18
  77. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +109 -21
  78. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js.map +1 -1
  79. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.d.ts +38 -0
  80. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js +46 -0
  81. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js.map +1 -1
  82. package/bundle/typescript/src/commands/game/sideQuest/utilities/splash.d.ts +6 -0
  83. package/bundle/typescript/src/commands/game/sideQuest/utilities/splash.js +60 -0
  84. package/bundle/typescript/src/commands/game/sideQuest/utilities/splash.js.map +1 -0
  85. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +31 -0
  86. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +41 -0
  87. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
  88. package/bundle/typescript/src/commands/game/sideQuest/utilities/web-character-generator.d.ts +29 -0
  89. package/bundle/typescript/src/commands/game/sideQuest/utilities/web-character-generator.js +33 -0
  90. package/bundle/typescript/src/commands/game/sideQuest/utilities/web-character-generator.js.map +1 -0
  91. package/bundle/typescript/src/commands/game/sideQuest-backlog.sub.cmd.js +16 -11
  92. package/bundle/typescript/src/commands/game/sideQuest-backlog.sub.cmd.js.map +1 -1
  93. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.d.ts +1 -0
  94. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +100 -42
  95. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
  96. package/bundle/typescript/src/commands/registry.js +1 -1
  97. package/bundle/typescript/src/commands/registry.js.map +1 -1
  98. package/bundle/typescript/src/commands/set/global.sub.cmd.js +1 -20
  99. package/bundle/typescript/src/commands/set/global.sub.cmd.js.map +1 -1
  100. package/bundle/typescript/src/generator.js +1 -0
  101. package/bundle/typescript/src/generator.js.map +1 -1
  102. package/bundle/typescript/src/templates/meteor/collection/tests.js +1 -1
  103. package/bundle/typescript/src/templates/meteor/collection/tests.js.ts +1 -1
  104. package/bundle/typescript/src/templates/react/test/test.js.jsx +31 -29
  105. package/bundle/typescript/src/templates/react/test/test.js.tsx +31 -29
  106. package/bundle/typescript/src/tools/browser/open-browser.d.ts +7 -0
  107. package/bundle/typescript/src/tools/browser/open-browser.js +21 -0
  108. package/bundle/typescript/src/tools/browser/open-browser.js.map +1 -0
  109. package/bundle/typescript/src/tools/pkg/pkg.class.js +12 -1
  110. package/bundle/typescript/src/tools/pkg/pkg.class.js.map +1 -1
  111. package/package.json +1 -1
  112. package/bundle/typescript/src/commands/game/battleship.sub.cmd.d.ts +0 -1
  113. package/bundle/typescript/src/commands/game/battleship.sub.cmd.js +0 -12
  114. package/bundle/typescript/src/commands/game/battleship.sub.cmd.js.map +0 -1
  115. package/bundle/typescript/src/commands/game/play.command.d.ts +0 -3
  116. package/bundle/typescript/src/commands/game/play.command.js +0 -18
  117. package/bundle/typescript/src/commands/game/play.command.js.map +0 -1
  118. package/bundle/typescript/src/commands/game/pong.sub.cmd.d.ts +0 -1
  119. package/bundle/typescript/src/commands/game/pong.sub.cmd.js +0 -12
  120. package/bundle/typescript/src/commands/game/pong.sub.cmd.js.map +0 -1
  121. package/bundle/typescript/src/commands/game/snake.sub.cmd.d.ts +0 -1
  122. package/bundle/typescript/src/commands/game/snake.sub.cmd.js +0 -12
  123. package/bundle/typescript/src/commands/game/snake.sub.cmd.js.map +0 -1
  124. package/bundle/typescript/src/commands/game/tetris.sub.cmd.d.ts +0 -1
  125. package/bundle/typescript/src/commands/game/tetris.sub.cmd.js +0 -12
  126. package/bundle/typescript/src/commands/game/tetris.sub.cmd.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import blessed from 'blessed';
2
- import { nameThem } from './utilities/identity.js';
2
+ import { nameThem, scrubHandles } from './utilities/identity.js';
3
3
  import { dirname } from 'path';
4
4
  import { capitalCase } from 'change-case';
5
5
  import { Category, Size, Rating } from './types/shared/item-enum.js';
@@ -13,9 +13,9 @@ import { pushSave, burnCloudSaveFor } from './utilities/cloud-saves.js';
13
13
  import { DOCWAGON_TIERS, RESUSC_FEE, DEATH_COMP } from './utilities/docwagon.js';
14
14
  import { isFence, LIFESTYLE_TIERS } from './utilities/commerce.js';
15
15
  import { bestFakeSin, wandRead, processArrest } from './utilities/sin.js';
16
- import { renderMapViewport } from './utilities/map-view.js';
16
+ import { renderMapViewport, mapCaption } from './utilities/map-view.js';
17
17
  import { tallestRoomRows } from './utilities/room-grid.js';
18
- import { renderRoomLayoutCompact, crewOfTable } from './utilities/room-view.js';
18
+ import { renderRoomLayoutCompact, crewOfTable, roomCaption } from './utilities/room-view.js';
19
19
  import { getPref } from './utilities/prefs.js';
20
20
  import { rollPool, formatRoll } from './utilities/dice.js';
21
21
  import { Direction } from './types/shared/direction-enum.js';
@@ -71,7 +71,7 @@ import { EdgeCommand } from './commands/edge.js';
71
71
  import { SheetCommand } from './commands/sheet.js';
72
72
  import { CallCommand } from './commands/call.js';
73
73
  import { EndCallCommand } from './commands/end-call.js';
74
- import { fuzzyPickName, levenshteinDistance } from './utilities/fuzzy-match.js';
74
+ import { fuzzyPickName, guessVerb } from './utilities/fuzzy-match.js';
75
75
  import { PickCommand } from './commands/pick.js';
76
76
  import { HackCommand } from './commands/hack.js';
77
77
  import { CastCommand } from './commands/cast.js';
@@ -102,6 +102,7 @@ import { ThreadCommand } from './commands/thread.js';
102
102
  import { RegisterCommand } from './commands/register.js';
103
103
  import { SpritesCommand } from './commands/sprites.js';
104
104
  import { StandbyCommand } from './commands/standby.js';
105
+ import { SustainCommand } from './commands/sustain.js';
105
106
  import { AbandonCommand } from './commands/abandon.js';
106
107
  import { UnravelCommand } from './commands/unravel.js';
107
108
  import { OrderCommand } from './commands/order.js';
@@ -456,8 +457,29 @@ export default class Game {
456
457
  heatBand() {
457
458
  if (this._runHeat <= 0)
458
459
  return undefined;
460
+ // NOBODY IS COMING, AND THAT IS CANON (oPqWB3CqzQmhpq3o2, player:
461
+ // "HTR assembling somewhere close, warning, but it never resulted in
462
+ // anything"). They were right, and the old line was the lie.
463
+ //
464
+ // SR5 p.352 gives HTR response times by the site's security level,
465
+ // and Run Faster p.220 extends it as neighbourhood zones: AA is
466
+ // 1D6+4 MINUTES, B is 1D6x5, and Zone 0 -- the lawless barrens --
467
+ // is 2D6 HOURS. Every shipped scene is a barrens district, so no
468
+ // response team reaches the player mid-run. Nothing arriving is the
469
+ // CORRECT outcome; promising an arrival was the defect.
470
+ //
471
+ // So the band now names what heat this high actually buys, which is
472
+ // not nothing: the ride home runs a Knight Errant checkpoint
473
+ // (checkpointOnRideHome), and at exactly this threshold the verifier
474
+ // there rolls 8 dice against a fake SIN instead of 6. Same number,
475
+ // deliberately -- a test pins the two together so the promise and
476
+ // the mechanic cannot drift apart.
477
+ //
478
+ // Security ratings per site are deferred by player ruling; when they
479
+ // land, a corporate site can honestly warn about a team that really
480
+ // is coming.
459
481
  if (this._runHeat >= 12)
460
- return `{red-fg}🔥 Heat: HTR assembling somewhere close{/red-fg}`;
482
+ return `{red-fg}🔥 Heat: nobody's coming out here -- they'll be waiting at the checkpoint{/red-fg}`;
461
483
  if (this._runHeat >= Game.CHECKPOINT_HEAT)
462
484
  return `{red-fg}🔥 Heat: sirens circling closer{/red-fg}`;
463
485
  if (this._runHeat >= 3)
@@ -1236,11 +1258,42 @@ export default class Game {
1236
1258
  entry.npc.deathClaimed = true;
1237
1259
  this.scene.removeActor(entry.npc.name);
1238
1260
  }
1261
+ this.returnSustainedForms(entry);
1239
1262
  const idx = this.companions.indexOf(entry);
1240
1263
  if (idx >= 0)
1241
1264
  this.companions.splice(idx, 1);
1242
1265
  Logger.getInstance().write(`Companion dismissed: ${entry.npc.name} -- ${reason}`);
1243
1266
  }
1267
+ /**
1268
+ * A FORM A SPRITE WAS CARRYING COMES HOME WHEN THE SPRITE GOES
1269
+ * (SR5 p.256 Sustain Complex Form; see commands/sustain.ts).
1270
+ *
1271
+ * The task hands a technomancer's complex form to a registered sprite
1272
+ * so the SPRITE eats the -2. That means the only entry point in the
1273
+ * game that moves a form off its weaver is also the only one that
1274
+ * could destroy it: dismiss, kill or park the sprite and the form
1275
+ * would go into the Resonance with it, silently, looking exactly like
1276
+ * a form the player had dropped on purpose.
1277
+ *
1278
+ * Canon says the technomancer "can then take over sustaining again",
1279
+ * so taking over is the natural end of the arrangement -- and a sprite
1280
+ * leaving is the arrangement ending whether or not anybody typed the
1281
+ * verb. The weave was never the sprite's; it was only being carried.
1282
+ *
1283
+ * Called from BOTH teardown paths on purpose. dismissCompanion covers
1284
+ * dismissal and standby (standbySpriteToResonance dismisses to park),
1285
+ * onActorRemoved covers death. Either alone would leave a hole that
1286
+ * only shows up as a missing form several minutes later.
1287
+ */
1288
+ returnSustainedForms(entry) {
1289
+ const held = entry.npc.sustainedForms;
1290
+ if (!held || held.length === 0)
1291
+ return;
1292
+ const owner = (entry.npc.allyOf ? this.scene?.getPlayerByName(entry.npc.allyOf) : undefined) ?? this.player;
1293
+ owner.sustainedForms.push(...held);
1294
+ entry.npc.sustainedForms = [];
1295
+ Logger.getInstance().logWithColor(`👥 ${entry.npc.name} lets go of ${held.map(f => f.key).join(', ')} -- the weave falls back to you, and so does the sustaining.`, 'yellow');
1296
+ }
1244
1297
  /**
1245
1298
  * An actor left the world (Scene.removeActor). For a companion shell
1246
1299
  * that DIED (not a deliberate dismissal -- those set deathClaimed
@@ -1265,6 +1318,8 @@ export default class Game {
1265
1318
  const entry = this.companions.find(c => c.npc.name === name);
1266
1319
  if (!entry)
1267
1320
  return;
1321
+ // A dead sprite still gives back what it was only carrying.
1322
+ this.returnSustainedForms(entry);
1268
1323
  const idx = this.companions.indexOf(entry);
1269
1324
  if (idx >= 0)
1270
1325
  this.companions.splice(idx, 1);
@@ -2154,6 +2209,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2154
2209
  CommandFactory.registerCommand('sprites', SpritesCommand);
2155
2210
  // STANDBY (p.256): the registered-sprite task that parks one for 1.
2156
2211
  CommandFactory.registerCommand('standby', StandbyCommand);
2212
+ CommandFactory.registerCommand('sustain', SustainCommand);
2157
2213
  // Walk out for good -- the taxi's irreversible half (mYTCzJbs...).
2158
2214
  CommandFactory.registerCommand('abandon', AbandonCommand);
2159
2215
  // Kill Complex Form (p.250) -- the Resonance counterpart to dispel.
@@ -2167,6 +2223,12 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2167
2223
  // Vertical travel by name (commands/climb.ts) -- shortcuts over
2168
2224
  // move, which already crosses levels.
2169
2225
  CommandFactory.registerCommand('climb', ClimbCommand);
2226
+ // The word a player actually typed (vkDz3cquad25GACpm). mantle is
2227
+ // six edits from climb, so no amount of typo tolerance was ever
2228
+ // going to find it -- a synonym has to be said out loud.
2229
+ CommandFactory.registerCommand('mantle', ClimbCommand);
2230
+ CommandFactory.registerCommand('scale', ClimbCommand);
2231
+ CommandFactory.registerCommand('clamber', ClimbCommand);
2170
2232
  CommandFactory.registerCommand('descend', DescendCommand);
2171
2233
  CommandFactory.registerCommand('run', RunCommand);
2172
2234
  CommandFactory.registerCommand('sprint', SprintCommand);
@@ -2230,6 +2292,53 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2230
2292
  determineStartRoom() {
2231
2293
  return this.scene.determineStartRoom();
2232
2294
  }
2295
+ /**
2296
+ * WHERE THE RUNNER IS STANDING, when the seed says.
2297
+ *
2298
+ * `startSpot` has been declared on player-seed.ts all along and
2299
+ * nothing read it FOR THE PLAYER -- NPCs get theirs applied inside
2300
+ * scene-factory, the runner got nothing. So spotOf() returned
2301
+ * undefined for the one actor a person controls, and every
2302
+ * SPOT-RELATIVE mechanic quietly did not apply to them: move.ts
2303
+ * derives climbSteps from the actor's spot, so with none there is no
2304
+ * path, no climb link and no climbing test at all. A repro bench with
2305
+ * a catwalk walked you up it with no roll.
2306
+ *
2307
+ * APPLIED AFTER THE PLACEMENT, and the precise reason is worth
2308
+ * stating because I first wrote it down wrong. The currentLocation
2309
+ * setter clears atSpot only when the room actually CHANGES
2310
+ * (`if (this._currentLocation !== room)`). On a fresh boot the player
2311
+ * is already in the start room, so either order would work there --
2312
+ * a reordering mutation stays green, and I am saying so rather than
2313
+ * letting the comment claim a guarantee its test does not give.
2314
+ *
2315
+ * It matters on the TRAVEL path below, where the runner really does
2316
+ * move from the hub into a new scene and the setter really does fire.
2317
+ * Applying after placement is correct in both cases, which is why it
2318
+ * is the order used in both -- resumeOpenRun documents the same
2319
+ * ordering for the same reason.
2320
+ *
2321
+ * What IS covered by a red-on-removal test is the call existing at
2322
+ * all: nothing read this field before.
2323
+ *
2324
+ * REFUSES A SPOT THE ROOM DOES NOT HAVE rather than setting a name
2325
+ * nothing answers to: an atSpot with no cell behind it is the
2326
+ * silently-inert state this codebase keeps finding, and the runner
2327
+ * standing nowhere is strictly better than the runner standing
2328
+ * somewhere imaginary.
2329
+ *
2330
+ * No shipped scene sets it -- scene1 and scene2 both leave it
2331
+ * undefined -- so this changes nothing that exists today.
2332
+ */
2333
+ applySeedStartSpot(seed) {
2334
+ const wanted = seed?.player?.startSpot;
2335
+ if (!wanted)
2336
+ return;
2337
+ const room = this.player.currentLocation;
2338
+ if (!room?.spots?.some(s => s.name === wanted))
2339
+ return;
2340
+ this.player.atSpot = wanted;
2341
+ }
2233
2342
  /**
2234
2343
  * Wires a fresh, always-unlocked path between the persistent home base
2235
2344
  * and wherever the player is starting the current job from. Clears the
@@ -2366,6 +2475,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2366
2475
  }
2367
2476
  this.scene.initialize(this);
2368
2477
  this.player.currentLocation = this.determineStartRoom();
2478
+ this.applySeedStartSpot(this.sceneSeed);
2369
2479
  this.registerCommands();
2370
2480
  // The description follows the rent from day one (see
2371
2481
  // syncHomeToLifestyle) -- a fresh session at the default Squatter tier
@@ -3231,7 +3341,24 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3231
3341
  // raw server error stitched into Krow's fiction read as an
3232
3342
  // instruction to "update the server" (real player note) -- it
3233
3343
  // means update THIS machine.
3234
- const skew = /runs engine ([\d.]+)/.exec(String(shared.declined));
3344
+ // THE SERVER'S REASON IS SPOKEN ALOUD, so it goes through the
3345
+ // identity rule first (5wjyaaY7EKGttGZLQ: "don't put player
3346
+ // names (doubleglizzy) in the message about 'Couldn't raise the
3347
+ // whole crew'. This should be character names").
3348
+ //
3349
+ // The `absent` list below was already fixed to name runners via
3350
+ // nameThem. This is its SIBLING and was missed: a decline comes
3351
+ // back as free text the server composed, and it can name the
3352
+ // seat it could not raise -- by account handle, because that is
3353
+ // what the seat plumbing scopes to. Stitched into Krow's quoted
3354
+ // dialogue, that put a person's site-wide identity in the
3355
+ // fiction.
3356
+ //
3357
+ // Scrubbed ONCE here rather than at each branch: two of the four
3358
+ // branches below interpolate it, and the next one added would
3359
+ // have had to remember.
3360
+ const declined = scrubHandles(String(shared.declined), this.crew.map(m => ({ handle: m.ghost?.owner, name: m.name })));
3361
+ const skew = /runs engine ([\d.]+)/.exec(declined);
3235
3362
  sharedDeclineNote = skew
3236
3363
  ? ` "Crew channel's scrambled tonight -- no job till it clears."\n{yellow-fg}(Out of character: engine mismatch -- this machine runs ${srMod?.engineVersion() ?? '?'}, the street runs ${skew[1]}. If yours is older: npm i -g @maka/maka-cli@latest, then relaunch. If newer, the street is still rolling out.){/yellow-fg}`
3237
3364
  : shared.code === 'unverified'
@@ -3242,8 +3369,8 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3242
3369
  : shared.code === 'not-your-table'
3243
3370
  // Leader-only crew jobs (ruling 2026-08-24): Krow takes
3244
3371
  // commissions from the head of the table, nobody else.
3245
- ? ` "${shared.declined} Want crew work? Take theirs, or seat a table of your own."`
3246
- : ` "Couldn't raise the whole crew -- ${shared.declined} No crew on the line, no job -- raise them and call again."`;
3372
+ ? ` "${declined} Want crew work? Take theirs, or seat a table of your own."`
3373
+ : ` "Couldn't raise the whole crew -- ${declined} No crew on the line, no job -- raise them and call again."`;
3247
3374
  // CREW EXCLUSIVITY (ruling 2026-08-24): a declined crew draft
3248
3375
  // never falls back to a solo quote -- the ping explains, and
3249
3376
  // the docket stays empty until the table answers.
@@ -3401,6 +3528,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3401
3528
  this.scene = await SceneSynthesizer.synthesizeFromJson(seed, this.player, false, false);
3402
3529
  this.scene.initialize(this);
3403
3530
  this.player.currentLocation = this.determineStartRoom();
3531
+ this.applySeedStartSpot(seed);
3404
3532
  // New job -- and the needs come due at the door (see
3405
3533
  // applyDepartureNeeds): edge only refills fed-and-slept, and ignored
3406
3534
  // needs land as locked fatigue. Lines ride the JOB banner below.
@@ -4366,10 +4494,10 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
4366
4494
  // justify the elevation bar and to trim the caption rows.
4367
4495
  const boxWidth = screenW > 0 ? Math.floor(screenW * Game.ROOM_DOCK_PCT) - 2 : undefined;
4368
4496
  const mapWidth = screenW > 0 ? Math.floor(screenW * Game.MAP_DOCK_PCT) - 2 : undefined;
4369
- const caption = (text, width) => {
4370
- const w = width ?? text.length;
4371
- return `{bold}${text.length > w ? `${text.slice(0, Math.max(1, w - 1))}…` : text}{/bold}`;
4372
- };
4497
+ // ONE CAPTION BUILDER, shared with the server push in headless.ts
4498
+ // -- see mapCaption. Two inline copies is how the district map ended
4499
+ // up captioned solo and blank on a shared run (RwPkFsRwd4c2uHvGN).
4500
+ const caption = mapCaption;
4373
4501
  // The district viewport must FIT ITS BOX. It was a hardcoded 15
4374
4502
  // columns, which was fine while the Map box was 35% wide and
4375
4503
  // silently overflowed into the Room box once it shrank to 12% --
@@ -4400,8 +4528,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
4400
4528
  isOtherPlayer: a => this.scene.isHumanControlled(a),
4401
4529
  });
4402
4530
  if (roomLines.length > 0) {
4403
- const spot = spotOf(this.player);
4404
- roomLines.push(caption(spot ? `@ ${spot}` : '(moving through)', boxWidth));
4531
+ // roomCaption owns BOTH halves now -- where you stand, and that
4532
+ // somebody here has no cell to be drawn in (S6b4TLQWq46RN5kGu).
4533
+ roomLines.push(caption(roomCaption(here, this.player), boxWidth));
4405
4534
  }
4406
4535
  this.setRoomOverlay(roomLines);
4407
4536
  }
@@ -4561,15 +4690,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
4561
4690
  // a note -- EXCEPT anything that ends the session, which only ever
4562
4691
  // gets a suggestion: a typo must never quit the game.
4563
4692
  const knownVerbs = [...Object.keys(CommandFactory.getAllRegisteredCommands()), 'help', 'clear', 'quit', 'exit'];
4564
- let guess = fuzzyPickName(verb, knownVerbs);
4565
- // The shared matcher refuses typo tolerance on words <= 3 chars (too
4566
- // risky for item/NPC names) -- but the verb list is small and
4567
- // distinct, so a unique edit-distance-1 hit is safe ("maop" -> "map").
4568
- if (!guess && verb.length >= 3) {
4569
- const close = knownVerbs.filter(v => levenshteinDistance(verb, v) <= 1);
4570
- if (close.length === 1)
4571
- guess = close[0];
4572
- }
4693
+ // A near-miss SPELLING beats a substring for verbs -- see
4694
+ // guessVerb, which owns the ordering and the reason.
4695
+ const guess = guessVerb(verb, knownVerbs);
4573
4696
  if (guess && guess !== verb) {
4574
4697
  if (guess === 'quit' || guess === 'exit') {
4575
4698
  return out(`I don't understand "${verb}" -- did you mean "${guess}"?`);