@maka/maka-cli 5.116.0 → 5.118.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 (104) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js +6 -1
  3. package/bundle/typescript/src/commands/game/sideQuest/commands/attack.js.map +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/commands/compile.js +3 -0
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/compile.js.map +1 -1
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/decompile.js +3 -6
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/decompile.js.map +1 -1
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/download.js +24 -6
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/download.js.map +1 -1
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.d.ts +7 -1
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.js +34 -23
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/enter-host.js.map +1 -1
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/go.d.ts +7 -7
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +30 -50
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +42 -19
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
  18. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.d.ts +16 -0
  19. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.js +95 -0
  20. package/bundle/typescript/src/commands/game/sideQuest/commands/hop.js.map +1 -0
  21. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js +3 -1
  22. package/bundle/typescript/src/commands/game/sideQuest/commands/jack.js.map +1 -1
  23. package/bundle/typescript/src/commands/game/sideQuest/commands/jackpoint.js +5 -7
  24. package/bundle/typescript/src/commands/game/sideQuest/commands/jackpoint.js.map +1 -1
  25. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +40 -8
  26. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
  27. package/bundle/typescript/src/commands/game/sideQuest/commands/map.d.ts +6 -0
  28. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +21 -74
  29. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -1
  30. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +44 -17
  31. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js.map +1 -1
  32. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js +1 -1
  33. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js.map +1 -1
  34. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js +2 -0
  35. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js.map +1 -1
  36. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +8 -5
  37. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
  38. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +2 -1
  39. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
  40. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +20 -2
  41. package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
  42. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js +2 -5
  43. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js.map +1 -1
  44. package/bundle/typescript/src/commands/game/sideQuest/engine-version.d.ts +1 -1
  45. package/bundle/typescript/src/commands/game/sideQuest/engine-version.js +1 -1
  46. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +1 -0
  47. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
  48. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +2 -0
  49. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js.map +1 -1
  50. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +4 -0
  51. package/bundle/typescript/src/commands/game/sideQuest/game.js +86 -31
  52. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  53. package/bundle/typescript/src/commands/game/sideQuest/models/host.d.ts +80 -0
  54. package/bundle/typescript/src/commands/game/sideQuest/models/host.js +91 -0
  55. package/bundle/typescript/src/commands/game/sideQuest/models/host.js.map +1 -0
  56. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +83 -9
  57. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +153 -42
  58. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  59. package/bundle/typescript/src/commands/game/sideQuest/models/room.d.ts +40 -9
  60. package/bundle/typescript/src/commands/game/sideQuest/models/room.js +73 -12
  61. package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
  62. package/bundle/typescript/src/commands/game/sideQuest/models/scene.d.ts +3 -0
  63. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +3 -0
  64. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
  65. package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +2 -0
  66. package/bundle/typescript/src/commands/game/sideQuest/types/seed/room-seed.d.ts +1 -0
  67. package/bundle/typescript/src/commands/game/sideQuest/types/seed/scene-seed.d.ts +2 -0
  68. package/bundle/typescript/src/commands/game/sideQuest/utilities/cloud-saves.js +40 -29
  69. package/bundle/typescript/src/commands/game/sideQuest/utilities/cloud-saves.js.map +1 -1
  70. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js +30 -10
  71. package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js.map +1 -1
  72. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.d.ts +10 -0
  73. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.js +142 -56
  74. package/bundle/typescript/src/commands/game/sideQuest/utilities/condition-report.js.map +1 -1
  75. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.d.ts +58 -0
  76. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.js +107 -0
  77. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-reach.js.map +1 -0
  78. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.d.ts +21 -1
  79. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +104 -20
  80. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js.map +1 -1
  81. package/bundle/typescript/src/commands/game/sideQuest/utilities/grids.d.ts +72 -0
  82. package/bundle/typescript/src/commands/game/sideQuest/utilities/grids.js +100 -0
  83. package/bundle/typescript/src/commands/game/sideQuest/utilities/grids.js.map +1 -0
  84. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic-actors.d.ts +9 -0
  85. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic-actors.js +98 -0
  86. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic-actors.js.map +1 -0
  87. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.d.ts +3 -2
  88. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.js +26 -6
  89. package/bundle/typescript/src/commands/game/sideQuest/utilities/ic.js.map +1 -1
  90. package/bundle/typescript/src/commands/game/sideQuest/utilities/line-editor.d.ts +1 -1
  91. package/bundle/typescript/src/commands/game/sideQuest/utilities/line-editor.js +5 -5
  92. package/bundle/typescript/src/commands/game/sideQuest/utilities/line-editor.js.map +1 -1
  93. package/bundle/typescript/src/commands/game/sideQuest/utilities/logo-mark.d.ts +13 -0
  94. package/bundle/typescript/src/commands/game/sideQuest/utilities/logo-mark.js +47 -0
  95. package/bundle/typescript/src/commands/game/sideQuest/utilities/logo-mark.js.map +1 -1
  96. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-roster.d.ts +62 -0
  97. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-roster.js +97 -0
  98. package/bundle/typescript/src/commands/game/sideQuest/utilities/matrix-roster.js.map +1 -0
  99. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js +11 -1
  100. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
  101. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.d.ts +10 -0
  102. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +24 -19
  103. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -1
  104. package/package.json +1 -1
@@ -1,4 +1,7 @@
1
1
  import blessed from 'blessed';
2
+ import { hostInteriorPanel } from './utilities/grid-view.js';
3
+ import { DEFAULT_GRID_PROVIDER, PUBLIC_GRID, globalGrid } from './utilities/grids.js';
4
+ import { hostsInReach, hostDockLine, gridVicinity } from './utilities/grid-reach.js';
2
5
  import { nameThem, scrubHandles } from './utilities/identity.js';
3
6
  import { dirname } from 'path';
4
7
  import { capitalCase } from 'change-case';
@@ -14,7 +17,7 @@ import { pushSave, burnCloudSaveFor, enqueueBoundPush, flushPushQueue, writeSpil
14
17
  import { DOCWAGON_TIERS, RESUSC_FEE, DEATH_COMP } from './utilities/docwagon.js';
15
18
  import { isFence, LIFESTYLE_TIERS, canonicalLifestyleTier } from './utilities/commerce.js';
16
19
  import { attachBrandMark, attachBrandMarkBottomRight } from './utilities/brand-mark.js';
17
- import { attachLogoMark } from './utilities/logo-mark.js';
20
+ import { logoPanelLines } from './utilities/logo-mark.js';
18
21
  import { bestFakeSin, wandRead, processArrest } from './utilities/sin.js';
19
22
  import { tickEphemerals } from './utilities/ephemeral.js';
20
23
  import { requestAlarmBeat, newAlarmBeatLatch, ALARM_STIMULUS } from './utilities/alarmed-staff.js';
@@ -26,7 +29,7 @@ import { rollPool, formatRoll } from './utilities/dice.js';
26
29
  import { Direction } from './types/shared/direction-enum.js';
27
30
  import { Logger } from './utilities/logger.js';
28
31
  import { runHostTurn } from './utilities/ic.js';
29
- import { leaveMatrix } from './utilities/planes.js';
32
+ import { leaveMatrix, endPersona } from './utilities/planes.js';
30
33
  import { CommandQueue } from './utilities/command-queue.js';
31
34
  import { currentSession } from './utilities/session-context.js';
32
35
  import { PlayersCommand } from './commands/players.js';
@@ -65,6 +68,7 @@ import { EquipmentCommand } from './commands/equipment.js';
65
68
  import { MapCommand } from './commands/map.js';
66
69
  import { SilentCommand } from './commands/silent.js';
67
70
  import { EnterHostCommand, ExitHostCommand } from './commands/enter-host.js';
71
+ import { HopCommand } from './commands/hop.js';
68
72
  import { RestCommand } from './commands/rest.js';
69
73
  import { ReloadCommand } from './commands/reload.js';
70
74
  import { SubdueCommand } from './commands/subdue.js';
@@ -1658,6 +1662,8 @@ export default class Game {
1658
1662
  // and while the tab stands, rest at the hideout recovers half (rest.ts;
1659
1663
  // "pay" squares it, pay.ts; "lifestyle" views and moves tiers).
1660
1664
  lifestyleTier = 'Squatter';
1665
+ /** The Big Ten grid a High lifestyle rides (SR5 p.222). A placeholder default until chargen offers the pick (grids.ts). */
1666
+ gridProvider = DEFAULT_GRID_PROVIDER;
1661
1667
  rentDebt = 0;
1662
1668
  /** The active lifestyle tier's row (falls back to Squatter). */
1663
1669
  get lifestyle() {
@@ -2286,6 +2292,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2286
2292
  // branch ROUTES a bare "exit" to this command while the persona is
2287
2293
  // inside a host, and 'exit-host' is the always-reachable name.
2288
2294
  CommandFactory.registerCommand('enter', EnterHostCommand);
2295
+ CommandFactory.registerCommand('hop', HopCommand);
2289
2296
  CommandFactory.registerCommand('exit-host', ExitHostCommand);
2290
2297
  CommandFactory.registerCommand('rest', RestCommand);
2291
2298
  CommandFactory.registerCommand('reload', ReloadCommand);
@@ -2661,6 +2668,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2661
2668
  throw new Error(`Scene generation failed: ${err.message}`);
2662
2669
  }
2663
2670
  this.scene.initialize(this);
2671
+ this.resolveHostGrids();
2664
2672
  this.player.currentLocation = this.determineStartRoom();
2665
2673
  this.applySeedStartSpot(this.sceneSeed);
2666
2674
  this.registerCommands();
@@ -2861,11 +2869,26 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2861
2869
  this._resumedAt = room;
2862
2870
  }
2863
2871
  /** The location a save carries: the current hub room and spot. */
2872
+ /** Each host's seeded grid word ('public' | 'local' | 'global:<corp>') against this scene's local grid. */
2873
+ resolveHostGrids() {
2874
+ for (const room of Object.values(this.scene.getRooms())) {
2875
+ const host = room.host;
2876
+ if (!host?.gridSeed)
2877
+ continue;
2878
+ const w = host.gridSeed.trim().toLowerCase();
2879
+ host.grid = w === 'public' ? PUBLIC_GRID : w === 'local' ? this.scene.localGrid : w.startsWith('global:') ? globalGrid(host.gridSeed.slice('global:'.length)) : undefined;
2880
+ }
2881
+ }
2864
2882
  hubLocationSnapshot() {
2865
- const room = this.player.currentLocation;
2883
+ // The BODY's room, never the persona's: jacked in, currentLocation is
2884
+ // wherever the persona stands (a host's room inside one), and a resume
2885
+ // wakes the meat, not the icon.
2886
+ const jackedIn = this.player.plane === 'matrix';
2887
+ const room = jackedIn ? (this.player.bodyRoom ?? this.player.currentLocation) : this.player.currentLocation;
2866
2888
  if (!room)
2867
2889
  return undefined;
2868
- return { room: room.name, ...(this.player.atSpot ? { spot: this.player.atSpot } : {}) };
2890
+ const spot = jackedIn ? undefined : this.player.atSpot;
2891
+ return { room: room.name, ...(spot ? { spot } : {}) };
2869
2892
  }
2870
2893
  /**
2871
2894
  * Everything a save restores beyond the seed synthesis: the player,
@@ -2897,6 +2920,8 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2897
2920
  // local file never knew -- that is the cloud repair's job, and the
2898
2921
  // sync protocol's, see the repair-visibility ruling in cloud-saves.)
2899
2922
  this.lifestyleTier = canonicalLifestyleTier(save.game.lifestyleTier) ?? 'Street';
2923
+ if (typeof save.game.gridProvider === 'string' && save.game.gridProvider.trim())
2924
+ this.gridProvider = save.game.gridProvider;
2900
2925
  this.rentDebt = save.game.rentDebt;
2901
2926
  this.syncHomeToLifestyle();
2902
2927
  this.player.lifestyleEdgeBonus = this.lifestyle.edgeBonus;
@@ -3163,6 +3188,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3163
3188
  player: serializePlayer(this.player),
3164
3189
  game: {
3165
3190
  location: this.hubLocationSnapshot(),
3191
+ gridProvider: this.gridProvider,
3166
3192
  lifestyleTier: this.lifestyleTier,
3167
3193
  rentDebt: this.rentDebt,
3168
3194
  tier: this._tier,
@@ -3411,7 +3437,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3411
3437
  this.player.linkLockedBy.clear();
3412
3438
  // Same enumeration, same reason: insideHost is persona state and these
3413
3439
  // paths end the persona without passing through planes.leaveMatrix.
3414
- this.player.insideHost = undefined;
3440
+ endPersona(this.player);
3415
3441
  this.player.astralTicks = 0;
3416
3442
  this.player.activeDeck = undefined;
3417
3443
  this.player.riggedDrone = undefined;
@@ -3515,7 +3541,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3515
3541
  this.player.linkLockedBy.clear();
3516
3542
  // Same enumeration, same reason: insideHost is persona state and these
3517
3543
  // paths end the persona without passing through planes.leaveMatrix.
3518
- this.player.insideHost = undefined;
3544
+ endPersona(this.player);
3519
3545
  this.player.astralTicks = 0;
3520
3546
  this.player.activeDeck = undefined;
3521
3547
  this.player.riggedDrone = undefined;
@@ -3967,7 +3993,11 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3967
3993
  // forward), and no blocking AI-redressing pass either -- the chunked
3968
3994
  // rooms pass already wrote this scene's prose.
3969
3995
  this.scene = await SceneSynthesizer.synthesizeFromJson(seed, this.player, false, false);
3996
+ // A run happens in the same metroplex: it rides the hub's local grid.
3997
+ if (this._hubScene)
3998
+ this.scene.localGrid = this._hubScene.localGrid;
3970
3999
  this.scene.initialize(this);
4000
+ this.resolveHostGrids();
3971
4001
  this.player.currentLocation = this.determineStartRoom();
3972
4002
  this.applySeedStartSpot(seed);
3973
4003
  // New job -- and the needs come due at the door (see
@@ -4546,9 +4576,6 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
4546
4576
  });
4547
4577
  this._statusBox = statusBox;
4548
4578
  screen.append(statusBox);
4549
- // The site's dotted logo fills the HUD's six rows at the far right
4550
- // (utilities/logo-mark.ts). Not keyable (see initInputBox).
4551
- attachLogoMark(screen, statusBox);
4552
4579
  }
4553
4580
  /**
4554
4581
  * THE MINIMAP (map-overlay wave 2026-08-24; split into a pair
@@ -5079,11 +5106,19 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5079
5106
  if (!this._mapBox || this.remoteSession)
5080
5107
  return;
5081
5108
  const here = this.player.currentLocation;
5082
- if (!here || this.player.plane === 'matrix') {
5109
+ if (!here) {
5083
5110
  this.hideMapOverlay();
5084
5111
  this.hideRoomOverlay();
5085
5112
  return;
5086
5113
  }
5114
+ // JACKED IN (player request 2026-09-02): the docks stay lit. The
5115
+ // district map keeps drawing -- the persona rides the same geography
5116
+ // its body sits in -- and the Room dock shows a host's floor while
5117
+ // you are inside one. Otherwise you are simply ON THE GRID (SR5
5118
+ // pp.220-221, p.246: outside a host a persona is on its grid, and a
5119
+ // grid has no floor to draw), so the dock carries the mark instead
5120
+ // of going dark.
5121
+ const onTheGrid = this.player.plane === 'matrix' && !this.player.insideHost;
5087
5122
  const screenW = Number(this._screen?.width) || 0;
5088
5123
  // Each box's inner width. Derived from the screen rather than read
5089
5124
  // off the widget: blessed resolves percentage geometry at render
@@ -5103,17 +5138,41 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5103
5138
  // characters (playtest 2026-08-25: "getting some artifacting 'g'";
5104
5139
  // ui.ts documents this same smear from column drift). Odd widths
5105
5140
  // keep the player marker exactly centred.
5106
- const mapInner = mapWidth ?? 15;
5107
- const mapView = Math.max(7, mapInner % 2 === 0 ? mapInner - 1 : mapInner);
5108
- const mapLines = renderMapViewport(this.scene.getRooms(), here, (r, d) => this.scene.barrierSealing(r, d), {
5109
- visited: this.player.visitedRooms,
5110
- arEyes: this.player.hasMatrixEyes(),
5111
- }, mapView, tallestRoomRows());
5112
- // The captions the HUD used to carry: where you are under the
5113
- // district, where you stand under the room.
5114
- if (mapLines.length > 0)
5115
- mapLines.push(caption(here.name, mapWidth));
5116
- this.setMapOverlay(mapLines);
5141
+ if (this.player.plane === 'matrix') {
5142
+ // THE GRID IS A FLATLAND OF ICONS (SR5 pp.217-218, p.246): the Map
5143
+ // dock shows the hosts overhead, not the district under the body.
5144
+ const hosts = hostsInReach(this.scene.getRooms(), this.player);
5145
+ const dockW = mapWidth ?? 15;
5146
+ const lines = hosts.length > 0
5147
+ ? hosts.map(h => hostDockLine(h, this.player, dockW))
5148
+ : ['{cyan-fg}nothing overhead{/cyan-fg}'];
5149
+ lines.push(caption(this.player.insideHost ? `inside ${this.player.insideHost.name}` : `on the grid from ${gridVicinity(this.player).name}`, mapWidth));
5150
+ this.setMapOverlay(lines);
5151
+ if (onTheGrid) {
5152
+ this.setRoomOverlay(logoPanelLines(Game.MAP_DOCK_ROWS - 2, boxWidth ?? 16));
5153
+ return;
5154
+ }
5155
+ // INSIDE A HOST there is no floor to draw (p.219, p.246): the dock
5156
+ // shows the interior's icons, not the room the body sits in.
5157
+ const inside = this.player.hostInside;
5158
+ if (inside) {
5159
+ this.setRoomOverlay(hostInteriorPanel(this.scene, this.player, inside, Game.MAP_DOCK_ROWS - 2, boxWidth ?? 16));
5160
+ return;
5161
+ }
5162
+ }
5163
+ else {
5164
+ const mapInner = mapWidth ?? 15;
5165
+ const mapView = Math.max(7, mapInner % 2 === 0 ? mapInner - 1 : mapInner);
5166
+ const mapLines = renderMapViewport(this.scene.getRooms(), here, (r, d) => this.scene.barrierSealing(r, d), {
5167
+ visited: this.player.visitedRooms,
5168
+ arEyes: this.player.hasMatrixEyes(),
5169
+ }, mapView, tallestRoomRows());
5170
+ // The captions the HUD used to carry: where you are under the
5171
+ // district, where you stand under the room.
5172
+ if (mapLines.length > 0)
5173
+ mapLines.push(caption(here.name, mapWidth));
5174
+ this.setMapOverlay(mapLines);
5175
+ }
5117
5176
  // A DECORATION MUST NEVER KILL THE RUN. This panel is pure derived
5118
5177
  // geometry -- if synthesis or rendering ever throws (a malformed
5119
5178
  // seed, a room shape no one anticipated), the right outcome is a
@@ -5427,16 +5486,12 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5427
5486
  withICTurn(actor, result) {
5428
5487
  if (result === null)
5429
5488
  return null;
5430
- const room = actor.currentLocation;
5431
- // Phase 1b widened this gate. It used to ask hostIsHunting, which is
5432
- // only true AFTER the host had made someone -- so the host could
5433
- // never notice you in the first place, and measurement said so:
5434
- // twelve runs, twelve cracked hosts, zero sightings. A host with a
5435
- // node gets its turn whenever a persona is standing in it, and
5436
- // ic.ts decides whether that turn is eyes or ice.
5437
- if (!room || actor.plane !== 'matrix' || !room.hasNode)
5489
+ // The host's turn happens INSIDE it (p.246-247): the ice acts on what
5490
+ // is in the host, and the persona's position says whether it is.
5491
+ const host = actor.hostInside;
5492
+ if (!host || actor.plane !== 'matrix')
5438
5493
  return result;
5439
- const turn = runHostTurn(room, actor);
5494
+ const turn = runHostTurn(host.over, actor, this.scene);
5440
5495
  if (turn.lines.length === 0 && turn.meta.length === 0)
5441
5496
  return result;
5442
5497
  // Dice to the Mechanics pane, and only for a human -- the same gate
@@ -5517,7 +5572,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
5517
5572
  // players" / "crew street"); the bare verb still answers quietly.
5518
5573
  { title: 'party', entries: [['crew', 'party'], ['hire'], ['dismiss'], ['train'], ['order'], ['lead'], ['command'], ['deploy'], ['recall']] },
5519
5574
  { title: 'magic', entries: [['spells'], ['cast'], ['summon', 'conjure'], ['project', 'astral'], ['return'], ['assense']] },
5520
- { title: 'matrix', entries: [['jack'], ['jackpoint'], ['deck'], ['load'], ['unload'], ['hack'], ['mark'], ['download'], ['enter'], ['exit-host'], ['tap', 'splice'], ['snoop'], ['overwatch', 'os'], ['pan'], ['ar'], ['aros'], ['silent'], ['reboot'], ['agent'], ['drone'], ['jump', 'rig']] },
5575
+ { title: 'matrix', entries: [['jack'], ['jackpoint'], ['deck'], ['load'], ['unload'], ['hack'], ['mark'], ['download'], ['enter'], ['exit-host'], ['hop'], ['tap', 'splice'], ['snoop'], ['overwatch', 'os'], ['pan'], ['ar'], ['aros'], ['silent'], ['reboot'], ['agent'], ['drone'], ['jump', 'rig']] },
5521
5576
  // The Emerged get their own shelf (player request: "there MUST be
5522
5577
  // resonance" -- matrix is the place, Resonance is the talent).
5523
5578
  // `sustain` shelves here and not under magic: the command is