@maka/maka-cli 5.61.0 → 5.63.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.
- package/bundle/typescript/package.json +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/advance.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/advance.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/ar.d.ts +34 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js +93 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.d.ts +7 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js +7 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.d.ts +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js +56 -7
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.d.ts +9 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +62 -23
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js +5 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.js +41 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/crew.d.ts +7 -14
- package/bundle/typescript/src/commands/game/sideQuest/commands/crew.js +86 -51
- package/bundle/typescript/src/commands/game/sideQuest/commands/crew.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js +6 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/follow.d.ts +37 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/follow.js +216 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/follow.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +23 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +30 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/install.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/install.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +6 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/lead.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/lead.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.d.ts +21 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +165 -59
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +5 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +6 -4
- package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/note.js +9 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/note.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/overwatch.js +3 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/overwatch.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/players.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/players.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/quality-trade.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/quality-trade.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/roles.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/roles.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.d.ts +21 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +95 -8
- package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +3 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.d.ts +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js +13 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js +11 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js +5 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js +21 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/tap.d.ts +49 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js +181 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js +4 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js +6 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.d.ts +13 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +85 -4
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +43 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +9 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.js +90 -25
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/headless.js +58 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +30 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +234 -63
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +19 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +31 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.d.ts +23 -4
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +54 -8
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/ui.js +21 -0
- package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.d.ts +74 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +184 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/earshot.d.ts +76 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/earshot.js +98 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/earshot.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/generation-capture.js +21 -9
- package/bundle/typescript/src/commands/game/sideQuest/utilities/generation-capture.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.d.ts +16 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +34 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +34 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js +3 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.d.ts +26 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.js +92 -7
- package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +19 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +28 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/surveillance.d.ts +33 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/surveillance.js +61 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/surveillance.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +12 -11
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/maka.js +26 -0
- package/bundle/typescript/src/maka.js.map +1 -1
- package/bundle/typescript/src/tools/sdk-loader/relocate.js +7 -0
- package/bundle/typescript/src/tools/sdk-loader/relocate.js.map +1 -1
- package/bundle/typescript/src/tools/self-spawn/self-spawn.d.ts +10 -0
- package/bundle/typescript/src/tools/self-spawn/self-spawn.js +68 -0
- package/bundle/typescript/src/tools/self-spawn/self-spawn.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { isLinked, CALL_COLOR } from './comm-style.js';
|
|
2
|
+
import { isWatched, camerasLive, canSnoopFeeds } from './surveillance.js';
|
|
3
|
+
import { Category } from '../types/shared/item-enum.js';
|
|
4
|
+
import { hint } from './hints.js';
|
|
5
|
+
/**
|
|
6
|
+
* AROs -- AUGMENTED REALITY OBJECTS (player request 2026-08-26: "we
|
|
7
|
+
* need AROs on anything online"). The 2075 street is not bare: anything
|
|
8
|
+
* broadcasting wears an icon in the eye of anyone whose commlink is up.
|
|
9
|
+
* Until now that layer existed only from the INSIDE -- a jacked-in
|
|
10
|
+
* persona saw hosts, PANs and camera clusters as icons (grid-view.ts),
|
|
11
|
+
* and a decker standing in the same room in the flesh saw a bar.
|
|
12
|
+
*
|
|
13
|
+
* This is the same objects seen from the meat side, and deliberately
|
|
14
|
+
* the SAME GLYPHS (● host, ▣ PAN, ◎ cameras, ▤ a loose device), so the
|
|
15
|
+
* two views read as one world looked at twice rather than two games.
|
|
16
|
+
*
|
|
17
|
+
* WHAT IS DELIBERATELY NOT HERE:
|
|
18
|
+
* - Anything not broadcasting. Silent PANs, air-gapped hosts and
|
|
19
|
+
* powered-down gear have no wireless presence to annotate; that is
|
|
20
|
+
* what silence and a hard line BUY, and grid-view.ts omits them for
|
|
21
|
+
* the same reason.
|
|
22
|
+
* - Loot you have not found. Only items already in plain sight get a
|
|
23
|
+
* tag (Room.plainSightItems -- the same subset take.ts lets you
|
|
24
|
+
* sweep unsearched). An AR overlay that x-rayed a drawer would hand
|
|
25
|
+
* the room's whole inventory to anyone with a commlink and make
|
|
26
|
+
* "search" pointless.
|
|
27
|
+
* - Marks, alert states and host internals. Those are a persona's
|
|
28
|
+
* read, bought by being out there on the grid. AR is the shop
|
|
29
|
+
* window, not the back office.
|
|
30
|
+
*/
|
|
31
|
+
/** Whether this actor's AR overlay is actually up right now. */
|
|
32
|
+
export function arSightUp(actor) {
|
|
33
|
+
// Meat only. A persona IS on the grid (grid-view.ts renders it), an
|
|
34
|
+
// astral form is nowhere near a commlink, and a jumped-in rigger is
|
|
35
|
+
// looking through a drone's cameras.
|
|
36
|
+
if (actor.plane !== 'meat')
|
|
37
|
+
return false;
|
|
38
|
+
// SILENCE IS NOT A BLINDFOLD (canon p.229 vs p.235-236, RAG-checked
|
|
39
|
+
// 2026-08-27). This used to return false while runningSilent, on the
|
|
40
|
+
// reasoning that the overlay rides the broadcast. Canon says
|
|
41
|
+
// otherwise: AR is what you RECEIVE (p.229), running silent is about
|
|
42
|
+
// what you EMIT -- it hides your icon from others and costs you -2
|
|
43
|
+
// dice on your own Matrix actions (p.235-236, see
|
|
44
|
+
// Player.matrixActionPenalty), and it "doesn't stop [your traffic]
|
|
45
|
+
// entirely". A silent runner still sees the street's AROs.
|
|
46
|
+
//
|
|
47
|
+
// Keeping the check here was ALSO a live bug: the district map paints
|
|
48
|
+
// its host markers off Player.hasMatrixEyes(), which never tested
|
|
49
|
+
// silence, so going silent printed prose about a dead overlay while
|
|
50
|
+
// the map kept painting hosts. hasMatrixEyes is the single source of
|
|
51
|
+
// truth now -- one predicate, so the two views cannot disagree.
|
|
52
|
+
return actor.hasMatrixEyes();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Every ARO in this room, one line each. Empty when AR is down, muted,
|
|
56
|
+
* hacked dark, or nothing here is online.
|
|
57
|
+
*/
|
|
58
|
+
export function aroTags(scene, actor, room) {
|
|
59
|
+
if (!arSightUp(actor))
|
|
60
|
+
return [];
|
|
61
|
+
const tags = [];
|
|
62
|
+
// THE HOST's public face. An air-gapped host has no wireless presence
|
|
63
|
+
// at all -- from the street it simply is not there (canReachHost is
|
|
64
|
+
// the persona-side twin of this rule).
|
|
65
|
+
if (room.hasNode && room.nodeAccess !== 'wired') {
|
|
66
|
+
tags.push(room.hostCracked
|
|
67
|
+
? `● ${room.name} host -- its marquee still turning, its walls in shreds.`
|
|
68
|
+
: `● ${room.name} host -- a public marquee turning slowly over the room.`);
|
|
69
|
+
}
|
|
70
|
+
// EVERY OTHER PRESENCE that is broadcasting. Same test grid-view.ts
|
|
71
|
+
// uses from the other side, so the two views never disagree about who
|
|
72
|
+
// is loud.
|
|
73
|
+
for (const other of scene.getActorsInRoom(room)) {
|
|
74
|
+
if (other === actor)
|
|
75
|
+
continue;
|
|
76
|
+
if (other.isIncapacitated() || !isLinked(other))
|
|
77
|
+
continue;
|
|
78
|
+
const master = other.getPanMaster();
|
|
79
|
+
if (!master)
|
|
80
|
+
continue;
|
|
81
|
+
tags.push(`▣ ${other.name} -- ${master.name} broadcasting, public profile up.`);
|
|
82
|
+
}
|
|
83
|
+
// THE EYES. Whether they are looped is knowledge you had to take from
|
|
84
|
+
// the host, so it shows only to whoever owns the feeds.
|
|
85
|
+
if (isWatched(room)) {
|
|
86
|
+
const rooms = scene.getRooms();
|
|
87
|
+
// The verb rides the tag: standing in the room IS the requirement
|
|
88
|
+
// for a direct connection (commands/tap.ts), so this is the one
|
|
89
|
+
// place the player is always in a position to use it.
|
|
90
|
+
tags.push(canSnoopFeeds(rooms, room, actor) && !camerasLive(rooms, room)
|
|
91
|
+
? `◎ Camera cluster -- wireless, and looping empty hallways for the house.`
|
|
92
|
+
: `◎ Camera cluster -- wireless, and watching.${hint(` ("tap" cables into it -- a slaved lens can't hide behind its host)`)}`);
|
|
93
|
+
}
|
|
94
|
+
// LOOSE DEVICES lying in plain sight. A wireless deck on a table
|
|
95
|
+
// announces itself; one in a drawer you never opened does not.
|
|
96
|
+
for (const item of room.inventory.getAllItems()) {
|
|
97
|
+
if (item.plane !== 'meat')
|
|
98
|
+
continue;
|
|
99
|
+
if (!room.plainSightItems.has(item.name.toLowerCase()))
|
|
100
|
+
continue;
|
|
101
|
+
if (!WIRELESS_CATEGORIES.has(item.category))
|
|
102
|
+
continue;
|
|
103
|
+
tags.push(`▤ ${item.name} -- powered up and on the grid.`);
|
|
104
|
+
}
|
|
105
|
+
return tags;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* THE HUD's AR READ (backlog item 4 -- Maka: "I still can't tell if I
|
|
109
|
+
* am in AR, there is no status icon"). TWO SLOTS, NEVER ONE. The HUD
|
|
110
|
+
* ranked five states down a single chain and could therefore only ever
|
|
111
|
+
* report the winner, so an overlay state was unreadable the moment
|
|
112
|
+
* anything outranked it. These answer different questions and have
|
|
113
|
+
* different cures:
|
|
114
|
+
*
|
|
115
|
+
* OVERLAY -- is the world being painted FOR me? Muting is my own
|
|
116
|
+
* choice ("ar" flips it back); a hacker cutting it is not
|
|
117
|
+
* ("reboot" is the only cure).
|
|
118
|
+
* LINK -- is my commlink BROADCASTING? That is what calls ride
|
|
119
|
+
* (call.ts wants a worn commlink) and what silence kills.
|
|
120
|
+
*
|
|
121
|
+
* They are genuinely independent -- canon p.229 vs p.235-236: AR is
|
|
122
|
+
* what you RECEIVE, silence is what you EMIT -- so a silent runner
|
|
123
|
+
* reads "AR ON | Link SILENT", both true at once. One slot could never
|
|
124
|
+
* say that, which was the whole complaint.
|
|
125
|
+
*
|
|
126
|
+
* The overlay slot asks arSightUp() rather than re-deriving state, so
|
|
127
|
+
* the HUD, the AR block on "look", and the district map's host markers
|
|
128
|
+
* all answer to one predicate and cannot drift apart. The old line
|
|
129
|
+
* tested `equipment.head?.commlink` for BOTH meanings, so a decker
|
|
130
|
+
* whose PAN master is a cyberdeck and who wears no commlink was told
|
|
131
|
+
* "Link offline" while their overlay painted happily -- literally the
|
|
132
|
+
* state Maka could not read.
|
|
133
|
+
*
|
|
134
|
+
* No gray anywhere (standing ruling): blessed's gray is ANSI
|
|
135
|
+
* bright-black and vanishes on stock dark palettes. White is the
|
|
136
|
+
* neutral.
|
|
137
|
+
*/
|
|
138
|
+
export function arStatusSlots(actor) {
|
|
139
|
+
const overlay = arSightUp(actor)
|
|
140
|
+
? `{${CALL_COLOR}-fg}◉ AR ON{/${CALL_COLOR}-fg}`
|
|
141
|
+
: actor.arOffline
|
|
142
|
+
// CUT outranks MUTED: the state that was done TO you, and that
|
|
143
|
+
// survives you flipping your own switch, is the one you need to
|
|
144
|
+
// see. Its cure is named once, on the link slot.
|
|
145
|
+
? `{red-fg}◌ AR CUT{/red-fg}`
|
|
146
|
+
: actor.arMuted
|
|
147
|
+
? `{white-fg}◌ AR OFF{/white-fg}`
|
|
148
|
+
: !actor.getPanMaster() && !actor.isTechnomancer()
|
|
149
|
+
? `{white-fg}◌ no AR rig{/white-fg}`
|
|
150
|
+
// Off-plane, or any future state that puts the overlay down
|
|
151
|
+
// without being one of the above. game.ts drops the slot
|
|
152
|
+
// entirely while off-plane -- a persona has its own HUD line.
|
|
153
|
+
: `{white-fg}◌ AR dark{/white-fg}`;
|
|
154
|
+
// The link slot keeps asking for a WORN commlink, because that is
|
|
155
|
+
// what call.ts asks for. A deck-only decker reading "AR ON | Link
|
|
156
|
+
// offline" is not a contradiction -- it is the true and previously
|
|
157
|
+
// unsayable answer: the overlay paints, nobody can call you.
|
|
158
|
+
const link = actor.equipment.head?.commlink == null
|
|
159
|
+
? `{white-fg}Link offline{/white-fg}`
|
|
160
|
+
: actor.arOffline
|
|
161
|
+
? `{red-fg}Link CRACKED -- reboot{/red-fg}`
|
|
162
|
+
: actor.runningSilent
|
|
163
|
+
? `{magenta-fg}Link SILENT{/magenta-fg}`
|
|
164
|
+
: `{${CALL_COLOR}-fg}Link online{/${CALL_COLOR}-fg}`;
|
|
165
|
+
return { overlay, link };
|
|
166
|
+
}
|
|
167
|
+
/** The tags as the standard cyan block, or '' when there is nothing to
|
|
168
|
+
* show -- callers append it to their own output. */
|
|
169
|
+
export function aroBlock(scene, actor, room) {
|
|
170
|
+
const tags = aroTags(scene, actor, room);
|
|
171
|
+
if (tags.length === 0)
|
|
172
|
+
return '';
|
|
173
|
+
return `{cyan-fg}AR OVERLAY:{/cyan-fg}\n${tags.map(t => ` {cyan-fg}${t}{/cyan-fg}`).join('\n')}`;
|
|
174
|
+
}
|
|
175
|
+
/** Gear that talks to the grid on its own. Weapons are absent on
|
|
176
|
+
* purpose: a smartgun's link belongs to its carrier's PAN, and it is
|
|
177
|
+
* already covered by their ▣ line. */
|
|
178
|
+
const WIRELESS_CATEGORIES = new Set([
|
|
179
|
+
Category.Commlink,
|
|
180
|
+
Category.Cyberdeck,
|
|
181
|
+
Category.RCC,
|
|
182
|
+
Category.Drone,
|
|
183
|
+
]);
|
|
184
|
+
//# sourceMappingURL=ar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ar.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/ar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Player } from '../models/player.js';
|
|
2
|
+
import type { NPC } from '../models/npc.js';
|
|
3
|
+
import type { Room } from '../models/room.js';
|
|
4
|
+
/**
|
|
5
|
+
* WHO CAN OVERHEAR A MURMUR (playtest, Deditri: "a private place for
|
|
6
|
+
* calls"). A call is audible to the room, and that is correct and
|
|
7
|
+
* load-bearing -- it is how a table learns what a partner is arranging,
|
|
8
|
+
* and NPC AIs react to the half of a conversation they catch. What was
|
|
9
|
+
* missing was anywhere to GO to avoid it: say.ts's call fan-out
|
|
10
|
+
* iterated `room.getActors()` flat, while ordinary speech (Room.say)
|
|
11
|
+
* had been spot-local since the "at" spots pass. Two code paths
|
|
12
|
+
* answering "who hears this" had drifted apart, so ducking into the
|
|
13
|
+
* booths changed nothing -- Patch at the bar and Old Cray in the booths
|
|
14
|
+
* overheard you either way.
|
|
15
|
+
*
|
|
16
|
+
* The place to duck into already existed. The hub seeds carry it and
|
|
17
|
+
* the fiction was already written for it: "High-backed booths built for
|
|
18
|
+
* quiet deals", "the dim table nobody chooses by accident", the Night
|
|
19
|
+
* Market's "shadowed edge". Nothing new is invented here; the call path
|
|
20
|
+
* just respects the position everyone else already respects.
|
|
21
|
+
*
|
|
22
|
+
* THE RULE, and why it is not Room.say's rule: room speech that finds
|
|
23
|
+
* nobody at your spot escalates to a SHOUT and carries room-wide -- that
|
|
24
|
+
* is how you call across a bar. A commlink held to your face never
|
|
25
|
+
* escalates; talking quietly into it is the whole point of it. So a
|
|
26
|
+
* murmur reaches your spot and stops there.
|
|
27
|
+
*
|
|
28
|
+
* WHAT DOES NOT BUY PRIVACY, deliberately:
|
|
29
|
+
* - CIRCULATING (no atSpot) is the compat state and means "anywhere in
|
|
30
|
+
* the room" -- it both reaches and is reached by everything. It is
|
|
31
|
+
* also the common case, and it stays exactly as loud as it has always
|
|
32
|
+
* been.
|
|
33
|
+
* - THE OPEN FLOOR is a real position but it is bare ground in the
|
|
34
|
+
* middle of the room, no cover, always visible (see spots.ts). Being
|
|
35
|
+
* apart from people is not the same as being out of earshot, and a
|
|
36
|
+
* runner muttering into their link in the middle of a bar is not
|
|
37
|
+
* having a private call.
|
|
38
|
+
* Privacy is furniture you go and stand at. You never get it by
|
|
39
|
+
* accident, and you never get it by standing back.
|
|
40
|
+
*
|
|
41
|
+
* Position is read off `Player.atSpot` through spots.ts on every call.
|
|
42
|
+
* Nothing here caches, stores, or derives a second notion of where
|
|
43
|
+
* anybody is.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* Everyone in the speaker's room close enough to catch a murmur.
|
|
47
|
+
* From a named spot: whoever shares it, plus anyone circulating.
|
|
48
|
+
* From the open floor or while circulating: the whole room.
|
|
49
|
+
*/
|
|
50
|
+
export declare function murmurAudience(speaker: Player): (Player | NPC)[];
|
|
51
|
+
export interface EarshotReading {
|
|
52
|
+
/** The room declares named places at all. When it doesn't there is
|
|
53
|
+
* nowhere in THIS room to duck into and the answer is another room. */
|
|
54
|
+
spotted: boolean;
|
|
55
|
+
/** Where the speaker stands; undefined = circulating (see spots.ts). */
|
|
56
|
+
spot?: string;
|
|
57
|
+
/** Circulating or on the open floor: nothing between you and the room. */
|
|
58
|
+
inTheOpen: boolean;
|
|
59
|
+
/** Who would catch a murmur from here. */
|
|
60
|
+
audience: (Player | NPC)[];
|
|
61
|
+
/** Nobody would. */
|
|
62
|
+
unheard: boolean;
|
|
63
|
+
/** Named places here with nobody at them -- where to go instead. */
|
|
64
|
+
quiet: string[];
|
|
65
|
+
}
|
|
66
|
+
export declare function readEarshot(speaker: Player): EarshotReading;
|
|
67
|
+
/**
|
|
68
|
+
* Named places in this room that nobody is standing at -- the honest
|
|
69
|
+
* answer to "so where do I go", thresholds sorted to the back. A
|
|
70
|
+
* CIRCULATING actor is at none of them and all of them at once (the
|
|
71
|
+
* compat rule), so their presence disqualifies every spot: there is
|
|
72
|
+
* nowhere to get away from somebody who is everywhere. The open floor
|
|
73
|
+
* is never offered; it is the one position that explicitly buys
|
|
74
|
+
* nothing.
|
|
75
|
+
*/
|
|
76
|
+
export declare function quietSpotsIn(room: Room, speaker: Player): string[];
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { sameSpot, spotOf, spotsActive, OPEN_FLOOR } from './spots.js';
|
|
2
|
+
/**
|
|
3
|
+
* WHO CAN OVERHEAR A MURMUR (playtest, Deditri: "a private place for
|
|
4
|
+
* calls"). A call is audible to the room, and that is correct and
|
|
5
|
+
* load-bearing -- it is how a table learns what a partner is arranging,
|
|
6
|
+
* and NPC AIs react to the half of a conversation they catch. What was
|
|
7
|
+
* missing was anywhere to GO to avoid it: say.ts's call fan-out
|
|
8
|
+
* iterated `room.getActors()` flat, while ordinary speech (Room.say)
|
|
9
|
+
* had been spot-local since the "at" spots pass. Two code paths
|
|
10
|
+
* answering "who hears this" had drifted apart, so ducking into the
|
|
11
|
+
* booths changed nothing -- Patch at the bar and Old Cray in the booths
|
|
12
|
+
* overheard you either way.
|
|
13
|
+
*
|
|
14
|
+
* The place to duck into already existed. The hub seeds carry it and
|
|
15
|
+
* the fiction was already written for it: "High-backed booths built for
|
|
16
|
+
* quiet deals", "the dim table nobody chooses by accident", the Night
|
|
17
|
+
* Market's "shadowed edge". Nothing new is invented here; the call path
|
|
18
|
+
* just respects the position everyone else already respects.
|
|
19
|
+
*
|
|
20
|
+
* THE RULE, and why it is not Room.say's rule: room speech that finds
|
|
21
|
+
* nobody at your spot escalates to a SHOUT and carries room-wide -- that
|
|
22
|
+
* is how you call across a bar. A commlink held to your face never
|
|
23
|
+
* escalates; talking quietly into it is the whole point of it. So a
|
|
24
|
+
* murmur reaches your spot and stops there.
|
|
25
|
+
*
|
|
26
|
+
* WHAT DOES NOT BUY PRIVACY, deliberately:
|
|
27
|
+
* - CIRCULATING (no atSpot) is the compat state and means "anywhere in
|
|
28
|
+
* the room" -- it both reaches and is reached by everything. It is
|
|
29
|
+
* also the common case, and it stays exactly as loud as it has always
|
|
30
|
+
* been.
|
|
31
|
+
* - THE OPEN FLOOR is a real position but it is bare ground in the
|
|
32
|
+
* middle of the room, no cover, always visible (see spots.ts). Being
|
|
33
|
+
* apart from people is not the same as being out of earshot, and a
|
|
34
|
+
* runner muttering into their link in the middle of a bar is not
|
|
35
|
+
* having a private call.
|
|
36
|
+
* Privacy is furniture you go and stand at. You never get it by
|
|
37
|
+
* accident, and you never get it by standing back.
|
|
38
|
+
*
|
|
39
|
+
* Position is read off `Player.atSpot` through spots.ts on every call.
|
|
40
|
+
* Nothing here caches, stores, or derives a second notion of where
|
|
41
|
+
* anybody is.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* Everyone in the speaker's room close enough to catch a murmur.
|
|
45
|
+
* From a named spot: whoever shares it, plus anyone circulating.
|
|
46
|
+
* From the open floor or while circulating: the whole room.
|
|
47
|
+
*/
|
|
48
|
+
export function murmurAudience(speaker) {
|
|
49
|
+
const others = speaker.currentLocation.getActors().filter(a => a !== speaker);
|
|
50
|
+
const spot = spotOf(speaker);
|
|
51
|
+
if (spot === undefined || spot === OPEN_FLOOR)
|
|
52
|
+
return others;
|
|
53
|
+
return others.filter(a => sameSpot(speaker, a));
|
|
54
|
+
}
|
|
55
|
+
export function readEarshot(speaker) {
|
|
56
|
+
const room = speaker.currentLocation;
|
|
57
|
+
const spot = spotOf(speaker);
|
|
58
|
+
const audience = murmurAudience(speaker);
|
|
59
|
+
return {
|
|
60
|
+
spotted: spotsActive(room),
|
|
61
|
+
spot,
|
|
62
|
+
inTheOpen: spot === undefined || spot === OPEN_FLOOR,
|
|
63
|
+
audience,
|
|
64
|
+
unheard: audience.length === 0,
|
|
65
|
+
quiet: quietSpotsIn(room, speaker),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A THRESHOLD is not a hiding place. The same name convention spots.ts
|
|
70
|
+
* uses to find the spot that owns a doorway (see entrySpotFor) -- an
|
|
71
|
+
* empty doorway is still empty, and still worth listing, but it is the
|
|
72
|
+
* worst place in the room to take a call and must never be the one the
|
|
73
|
+
* report recommends.
|
|
74
|
+
*/
|
|
75
|
+
const DOORISH = /door|entrance|entry|threshold|gate/i;
|
|
76
|
+
/**
|
|
77
|
+
* Named places in this room that nobody is standing at -- the honest
|
|
78
|
+
* answer to "so where do I go", thresholds sorted to the back. A
|
|
79
|
+
* CIRCULATING actor is at none of them and all of them at once (the
|
|
80
|
+
* compat rule), so their presence disqualifies every spot: there is
|
|
81
|
+
* nowhere to get away from somebody who is everywhere. The open floor
|
|
82
|
+
* is never offered; it is the one position that explicitly buys
|
|
83
|
+
* nothing.
|
|
84
|
+
*/
|
|
85
|
+
export function quietSpotsIn(room, speaker) {
|
|
86
|
+
if (!spotsActive(room))
|
|
87
|
+
return [];
|
|
88
|
+
const others = room.getActors().filter(a => a !== speaker);
|
|
89
|
+
if (others.some(a => spotOf(a) === undefined))
|
|
90
|
+
return [];
|
|
91
|
+
const taken = new Set(others.map(a => spotOf(a)));
|
|
92
|
+
const mine = spotOf(speaker);
|
|
93
|
+
const empty = (room.spots ?? [])
|
|
94
|
+
.map(s => s.name)
|
|
95
|
+
.filter(name => name !== OPEN_FLOOR && name !== mine && !taken.has(name));
|
|
96
|
+
return [...empty.filter(n => !DOORISH.test(n)), ...empty.filter(n => DOORISH.test(n))];
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=earshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"earshot.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/earshot.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAW,CAAC,CAAC,CAAC;AAC5D,CAAC;AAkBD,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO;QACL,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC;QAC1B,IAAI;QACJ,SAAS,EAAE,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU;QACpD,QAAQ;QACR,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC9B,KAAK,EAAE,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,GAAG,qCAAqC,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU,EAAE,OAAe;IACtD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAW,CAAC,KAAK,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAW,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAChB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC"}
|
|
@@ -52,15 +52,27 @@ export class GenerationCapture {
|
|
|
52
52
|
prompt: clampPrompt(rec.prompt ?? ''),
|
|
53
53
|
reply: clampReply(rec.reply ?? ''),
|
|
54
54
|
});
|
|
55
|
-
// EVICT
|
|
56
|
-
//
|
|
57
|
-
// first-12-wins
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
// EVICT BY VALUE, NOT BY POSITION (fixed 2026-08-27; supersedes the
|
|
56
|
+
// 2026-08-26 evict-oldest fix, which superseded the original
|
|
57
|
+
// first-12-wins refusal). Both earlier policies were positional,
|
|
58
|
+
// and the first production batch proved position is the wrong axis
|
|
59
|
+
// outright: 12 records, exactly MAX_RECORDS, and pipeline 1 was
|
|
60
|
+
// entirely absent along with pipeline 2's skeleton. But reaching
|
|
61
|
+
// pipeline 3 MEANS pipelines 1 and 2 failed -- so evict-oldest had
|
|
62
|
+
// thrown away precisely the fault records and kept the successful
|
|
63
|
+
// run. The corpus preserved the successes and discarded the faults,
|
|
64
|
+
// the exact inverse of what this module exists for.
|
|
65
|
+
//
|
|
66
|
+
// Successes are cheap and numerous (one per stage per pipeline);
|
|
67
|
+
// faults are the entire point. So when the buffer is full, drop the
|
|
68
|
+
// OLDEST ACCEPTED record, and only fall back to dropping the oldest
|
|
69
|
+
// fault when there is nothing else left to give up. A 12-slot
|
|
70
|
+
// buffer under this policy would have kept everything interesting
|
|
71
|
+
// from that run and lost nothing that mattered.
|
|
72
|
+
while (this.records.length > this.MAX_RECORDS) {
|
|
73
|
+
const victim = this.records.findIndex(r => r.outcome === 'accepted');
|
|
74
|
+
this.records.splice(victim === -1 ? 0 : victim, 1);
|
|
75
|
+
}
|
|
64
76
|
}
|
|
65
77
|
/** Writes only when something was actually captured. Never throws --
|
|
66
78
|
* a corpus is a nice-to-have and must never cost the player a run. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generation-capture.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/generation-capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA4DrC;;sDAEsD;AACtD,SAAS,WAAW,CAAC,IAAY,EAAE,GAAG,GAAG,MAAM;IAC7C,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACxB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,GAAG,GAAG,sBAAsB,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;AACnG,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,GAAG,GAAG,MAAM;IAC5C,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,mBAAmB,IAAI,CAAC,MAAM,GAAG,GAAG,SAAS,CAAC;AACxG,CAAC;AAWD,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAC,OAAO,GAAqB,EAAE,CAAC;IACtC,MAAM,CAAC,UAAU,CAAqB;IACtC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IACxB;mEAC+D;IACvD,MAAM,CAAU,WAAW,GAAG,EAAE,CAAC;IACzC,0EAA0E;IAClE,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC;IAE9B;;;;;;;;;;;;;OAaG;IACK,MAAM,CAAC,IAAI,CAA+C;IAElE,MAAM,CAAC,KAAK,CAAC,WAAmB,EAAE,IAAY,EAAE,IAAqC;QACnF,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,GAAmB;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,GAAG,GAAG;YACN,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;YACrC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SACnC,CAAC,CAAC;QACH,oEAAoE;QACpE,
|
|
1
|
+
{"version":3,"file":"generation-capture.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/generation-capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA4DrC;;sDAEsD;AACtD,SAAS,WAAW,CAAC,IAAY,EAAE,GAAG,GAAG,MAAM;IAC7C,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACxB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,GAAG,GAAG,sBAAsB,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;AACnG,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,GAAG,GAAG,MAAM;IAC5C,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,mBAAmB,IAAI,CAAC,MAAM,GAAG,GAAG,SAAS,CAAC;AACxG,CAAC;AAWD,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAC,OAAO,GAAqB,EAAE,CAAC;IACtC,MAAM,CAAC,UAAU,CAAqB;IACtC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IACxB;mEAC+D;IACvD,MAAM,CAAU,WAAW,GAAG,EAAE,CAAC;IACzC,0EAA0E;IAClE,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC;IAE9B;;;;;;;;;;;;;OAaG;IACK,MAAM,CAAC,IAAI,CAA+C;IAElE,MAAM,CAAC,KAAK,CAAC,WAAmB,EAAE,IAAY,EAAE,IAAqC;QACnF,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,GAAmB;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,OAAO;QAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,GAAG,GAAG;YACN,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;YACrC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SACnC,CAAC,CAAC;QACH,oEAAoE;QACpE,6DAA6D;QAC7D,iEAAiE;QACjE,mEAAmE;QACnE,gEAAgE;QAChE,iEAAiE;QACjE,mEAAmE;QACnE,kEAAkE;QAClE,oEAAoE;QACpE,oDAAoD;QACpD,EAAE;QACF,iEAAiE;QACjE,oEAAoE;QACpE,oEAAoE;QACpE,8DAA8D;QAC9D,kEAAkE;QAClE,gDAAgD;QAChD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC;YACrE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED;2EACuE;IACvE,MAAM,CAAC,KAAK,CAAC,OAA+B;QAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEtC,mEAAmE;QACnE,mEAAmE;QACnE,6DAA6D;QAC7D,8DAA8D;QAC9D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,KAAK,GAAkB;gBAC3B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO;gBACP,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC;YACF,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;YAAC,MAAM,CAAC;gBACP,2DAA2D;YAC7D,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAC7B,gEAAgE;QAChE,qEAAqE;QACrE,mEAAmE;QACnE,mEAAmE;QACnE,kEAAkE;QAClE,oBAAoB;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,IAAI,CAAC,IAAI,IAAI,EAAE,iBAAiB,CAAC,UAAU,OAAO,CAAC,CAAC;QAC5G,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;gBACtC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO;gBACP,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACrB,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,OAAO,CAAC,MAAM,iBAAiB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,+CAA+C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjI,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QACpB,CAAC;IACH,CAAC"}
|
|
@@ -12,5 +12,21 @@ import { Scene } from '../models/scene.js';
|
|
|
12
12
|
* air-gapped, ◆ persona, ▣ PAN, ◇ data.
|
|
13
13
|
*/
|
|
14
14
|
export declare function gridIcons(scene: Scene, actor: Player, room: Room): string[];
|
|
15
|
+
/**
|
|
16
|
+
* THE ROOM AS THE GRID DRAWS IT (player ruling 2026-08-26: "looking in
|
|
17
|
+
* the matrix shouldn't show the meatworld"). A persona's `look` used to
|
|
18
|
+
* open with the room's own meat prose -- steam off the noodle pot, the
|
|
19
|
+
* cracked vinyl, whoever is leaning on the counter. None of that is
|
|
20
|
+
* where a persona stands: the grid OVERLAYS a space, it does not
|
|
21
|
+
* furnish it, and a decker reading furniture they cannot touch (from a
|
|
22
|
+
* body slumped rooms away) is the plane fiction coming apart.
|
|
23
|
+
*
|
|
24
|
+
* So this is the orientation that replaces the prose: the room's NAME
|
|
25
|
+
* -- icons are labelled, and the grid map (map.ts) lists rooms by name
|
|
26
|
+
* for exactly the same reason -- and how dense the local grid is. The
|
|
27
|
+
* host itself is deliberately NOT described here: it is an ICON, and
|
|
28
|
+
* gridIcons below already names it with its state and its verbs.
|
|
29
|
+
*/
|
|
30
|
+
export declare function gridSculpt(actor: Player, room: Room): string;
|
|
15
31
|
/** The icons rendered as the standard cyan block, or the thin-grid line. */
|
|
16
32
|
export declare function gridIconBlock(scene: Scene, actor: Player, room: Room): string;
|
|
@@ -58,11 +58,44 @@ export function gridIcons(scene, actor, room) {
|
|
|
58
58
|
icons.push(`◎ Camera cluster -- live, and answering to YOU as much as the house. ("snoop <room>" watches remotely)`);
|
|
59
59
|
}
|
|
60
60
|
else {
|
|
61
|
-
|
|
61
|
+
// Seen from the grid, the cluster is worth naming as a WAY IN,
|
|
62
|
+
// not just a hazard (backlog item 10): it is slaved to the host,
|
|
63
|
+
// and a cable into a slave is a road to its master (p.233). The
|
|
64
|
+
// catch is that a persona cannot hold a cable -- so this reads as
|
|
65
|
+
// something your BODY could do, which is the price the rule
|
|
66
|
+
// charges. See commands/tap.ts.
|
|
67
|
+
icons.push(`◎ Camera cluster -- live, feeding the site's host. Loud acts here travel. (own the host to loop them -- or walk in and "tap" a lens in the flesh: slaved to the host means a key to the host)`);
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
return icons;
|
|
65
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* THE ROOM AS THE GRID DRAWS IT (player ruling 2026-08-26: "looking in
|
|
74
|
+
* the matrix shouldn't show the meatworld"). A persona's `look` used to
|
|
75
|
+
* open with the room's own meat prose -- steam off the noodle pot, the
|
|
76
|
+
* cracked vinyl, whoever is leaning on the counter. None of that is
|
|
77
|
+
* where a persona stands: the grid OVERLAYS a space, it does not
|
|
78
|
+
* furnish it, and a decker reading furniture they cannot touch (from a
|
|
79
|
+
* body slumped rooms away) is the plane fiction coming apart.
|
|
80
|
+
*
|
|
81
|
+
* So this is the orientation that replaces the prose: the room's NAME
|
|
82
|
+
* -- icons are labelled, and the grid map (map.ts) lists rooms by name
|
|
83
|
+
* for exactly the same reason -- and how dense the local grid is. The
|
|
84
|
+
* host itself is deliberately NOT described here: it is an ICON, and
|
|
85
|
+
* gridIcons below already names it with its state and its verbs.
|
|
86
|
+
*/
|
|
87
|
+
export function gridSculpt(actor, room) {
|
|
88
|
+
const header = `{cyan-fg}THE GRID :: ${room.name.toUpperCase()}{/cyan-fg}`;
|
|
89
|
+
// Thin ground says nothing extra on purpose: gridIconBlock's own
|
|
90
|
+
// empty-case line already calls it thin, and where there ARE icons
|
|
91
|
+
// they speak for themselves. Only a host earns a second line.
|
|
92
|
+
if (!room.hasNode)
|
|
93
|
+
return header;
|
|
94
|
+
const ground = canReachHost(actor, room)
|
|
95
|
+
? `Dense ground -- a host's architecture stands over this patch, and everything on it answers to that.`
|
|
96
|
+
: `Dead ground -- there is architecture here, but no door onto it from the wireless grid.`;
|
|
97
|
+
return `${header}\n{cyan-fg}${ground}{/cyan-fg}`;
|
|
98
|
+
}
|
|
66
99
|
/** The icons rendered as the standard cyan block, or the thin-grid line. */
|
|
67
100
|
export function gridIconBlock(scene, actor, room) {
|
|
68
101
|
const icons = gridIcons(scene, actor, room);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid-view.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/grid-view.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"grid-view.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/grid-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -600,6 +600,40 @@ export const OPEN_FLOOR_NAME = 'open floor';
|
|
|
600
600
|
function clamp(n, lo, hi) { return Math.max(lo, Math.min(hi, n)); }
|
|
601
601
|
function jitter(rng) { return Math.floor(rng() * 3) - 1; }
|
|
602
602
|
function chebyshev(a, b) { return Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y)); }
|
|
603
|
+
/**
|
|
604
|
+
* LATENT HAZARD, investigated 2026-08-27 and deliberately NOT fixed:
|
|
605
|
+
* this scans a SQUARE neighbourhood with no wall constraint, so an exit
|
|
606
|
+
* cell whose wall midpoint is taken can in principle be walked one step
|
|
607
|
+
* INWARD, off its wall and into open floor. That is the shape of the
|
|
608
|
+
* open backlog item "the back door is in the middle of the room" -- but
|
|
609
|
+
* it is NOT that bug. Probed with a tiny room, four exits and a
|
|
610
|
+
* deliberately crowded north wall: all four exit cells stayed on their
|
|
611
|
+
* walls, because the r=1 ring reaches the along-wall neighbours before
|
|
612
|
+
* any interior cell. It needs a fully occupied wall ROW to bite, which
|
|
613
|
+
* the placement order makes hard to arrange. Left alone rather than
|
|
614
|
+
* fixed speculatively.
|
|
615
|
+
*
|
|
616
|
+
* WHERE THAT BUG ACTUALLY LIVES, for whoever picks the item up (probed,
|
|
617
|
+
* not guessed -- all 25 shipped seed rooms are clean, so it only bites
|
|
618
|
+
* GENERATED scenes):
|
|
619
|
+
* 1. Room.namedDoorwayFor() rescues only ONE doorway-named spot per
|
|
620
|
+
* room -- it is a `.find`, singular. A room drafted with both a
|
|
621
|
+
* "front door" and a "back door" binds the first and leaves the
|
|
622
|
+
* second attached to no exit, however many exits are free.
|
|
623
|
+
* 2. Any spot left unbound falls through to the "unplaced spots:
|
|
624
|
+
* spread out" sampler at the bottom of synthesizeGrid, which is a
|
|
625
|
+
* max-min distance rejection sample with NO perimeter constraint.
|
|
626
|
+
* Correct for a table, wrong for a door: it seats the thing in
|
|
627
|
+
* open floor. Reproduced at (1,4) of a 12x8 room.
|
|
628
|
+
* 3. namedDoorwayFor only fires at all when some exit direction is
|
|
629
|
+
* UNCLAIMED, so a room whose every exit carries a seed `atSpot`
|
|
630
|
+
* pointing at non-doorway furniture strands its doorway spot the
|
|
631
|
+
* same way even when there is only one.
|
|
632
|
+
* The multi-exit centroid hub rule below is NOT implicated: it is
|
|
633
|
+
* reachable only for a spot the seed explicitly bound to several exits,
|
|
634
|
+
* and Night Market's "stalls" -- the case it was written for -- places
|
|
635
|
+
* correctly.
|
|
636
|
+
*/
|
|
603
637
|
function nearestFree(start, occupied, dims, exists) {
|
|
604
638
|
if (exists(start) && !occupied.has(key(start)))
|
|
605
639
|
return start;
|