@maka/maka-cli 5.63.1 → 5.65.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/ar.js +29 -8
- package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/ask.d.ts +42 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/ask.js +86 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/ask.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.d.ts +29 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js +151 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.d.ts +40 -13
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js +107 -25
- package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.d.ts +11 -15
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js +13 -16
- package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/buy.d.ts +8 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/buy.js +30 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/buy.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.d.ts +40 -49
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js +121 -160
- package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +29 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.d.ts +7 -8
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +13 -13
- package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.js +22 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.d.ts +30 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.js +65 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/cover.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/dispel.d.ts +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/dispel.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/dispel.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +25 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.d.ts +2 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js +18 -10
- package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/journal.d.ts +44 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/journal.js +136 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/journal.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.d.ts +20 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +157 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +18 -4
- package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/move.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.d.ts +2 -3
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js +2 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/pick.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/players.js +8 -2
- package/bundle/typescript/src/commands/game/sideQuest/commands/players.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/posture.d.ts +45 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/posture.js +115 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/posture.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +46 -12
- package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +30 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js +11 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.js +12 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/take.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.d.ts +47 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.js +91 -5
- package/bundle/typescript/src/commands/game/sideQuest/commands/talk.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.d.ts +20 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.js +61 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/time.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.d.ts +17 -0
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.js +136 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/use.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.d.ts +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js +15 -1
- package/bundle/typescript/src/commands/game/sideQuest/engine-version.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.d.ts +128 -44
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +551 -254
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js +82 -84
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-factory.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.d.ts +23 -4
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +95 -79
- package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/seed-migration.d.ts +30 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/seed-migration.js +176 -0
- package/bundle/typescript/src/commands/game/sideQuest/factories/seed-migration.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +104 -0
- package/bundle/typescript/src/commands/game/sideQuest/game.js +268 -16
- package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/headless-harness.d.ts +78 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless-harness.js +188 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless-harness.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.d.ts +5 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.js +78 -0
- package/bundle/typescript/src/commands/game/sideQuest/headless.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/_index.d.ts +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/_index.js +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/_index.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/device.d.ts +121 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/device.js +145 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/device.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/door.d.ts +27 -8
- package/bundle/typescript/src/commands/game/sideQuest/models/door.js +15 -10
- package/bundle/typescript/src/commands/game/sideQuest/models/door.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +143 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +253 -30
- package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +68 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js +102 -0
- package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/room.d.ts +80 -34
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js +126 -54
- package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.d.ts +1 -4
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +0 -22
- package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/scenes/scene1.json +78 -109
- package/bundle/typescript/src/commands/game/sideQuest/scenes/scene2.json +4 -101
- package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/device-seed.d.ts +52 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/device-seed.js +2 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/device-seed.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/legacy-puzzle-seed.d.ts +63 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/legacy-puzzle-seed.js +2 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/legacy-puzzle-seed.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/player-seed.d.ts +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/room-seed.d.ts +4 -0
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/scene-seed.d.ts +3 -2
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.d.ts +2 -28
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js +1 -14
- package/bundle/typescript/src/commands/game/sideQuest/types/shared/abstracts.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/ui.js +24 -0
- package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/affordances.d.ts +55 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/affordances.js +36 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/affordances.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.d.ts +22 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +26 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-dump.js +6 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-dump.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-review.d.ts +45 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-review.js +116 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog-review.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.d.ts +73 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.js +56 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/backlog.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js +37 -4
- package/bundle/typescript/src/commands/game/sideQuest/utilities/combat-exchange.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/credentials.d.ts +26 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/credentials.js +48 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/credentials.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/devices.d.ts +23 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/devices.js +55 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/devices.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.d.ts +57 -2
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js +46 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/fuzzy-match.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.d.ts +38 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.js +42 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/log-style.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js +72 -17
- package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/playtester.d.ts +50 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/playtester.js +43 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/playtester.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.d.ts +14 -3
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +45 -31
- 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 +66 -8
- package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +81 -15
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +142 -33
- package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/utilities/use-target.d.ts +88 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/use-target.js +113 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/use-target.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/world-clock.d.ts +83 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/world-clock.js +106 -0
- package/bundle/typescript/src/commands/game/sideQuest/utilities/world-clock.js.map +1 -0
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +54 -5
- package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
- package/bundle/typescript/src/maka.js +1 -1
- package/bundle/typescript/src/maka.js.map +1 -1
- package/bundle/typescript/src/tools/sdk-loader/relocate.d.ts +19 -2
- package/bundle/typescript/src/tools/sdk-loader/relocate.js +22 -2
- package/bundle/typescript/src/tools/sdk-loader/relocate.js.map +1 -1
- package/package.json +1 -1
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.d.ts +0 -6
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js +0 -72
- package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js.map +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.d.ts +0 -6
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js +0 -26
- package/bundle/typescript/src/commands/game/sideQuest/factories/puzzle-factory.js.map +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.d.ts +0 -143
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +0 -366
- package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js.map +0 -1
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.d.ts +0 -28
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.js +0 -2
- package/bundle/typescript/src/commands/game/sideQuest/types/seed/puzzle-seed.js.map +0 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { matchesCredential } from '../utilities/credentials.js';
|
|
2
|
+
import { AFFORDANCE_FLAVOR, verbsFor } from '../utilities/affordances.js';
|
|
3
|
+
import { hint } from '../utilities/hints.js';
|
|
4
|
+
/**
|
|
5
|
+
* A DEVICE: a thing in a room that is shut and can be opened.
|
|
6
|
+
*
|
|
7
|
+
* The replacement for Puzzle, and the difference is not cosmetic. A
|
|
8
|
+
* puzzle was a riddle wearing the costume of an object -- it had an
|
|
9
|
+
* answer, a prerequisite, a "solved" flag and a burnable shortcut, and
|
|
10
|
+
* the fiction had to be bent around that shape. A device is an OBJECT
|
|
11
|
+
* with an interface, and the verbs that work it are the ones that would
|
|
12
|
+
* work the real thing. The user's framing is the whole specification:
|
|
13
|
+
* "A lock is not a puzzle, it has a key. A keypad has an interface (to
|
|
14
|
+
* use). An NPC in the doorway can be persuaded/bluffed/conned to move
|
|
15
|
+
* aside. A persistent forcewall can be dispelled."
|
|
16
|
+
*
|
|
17
|
+
* A DEVICE IS ALWAYS ROOM-OWNED. There is no Device hanging off a Door,
|
|
18
|
+
* because a keypad beside a grate physically stands in ONE room -- the
|
|
19
|
+
* one you have to be standing in to reach it. Puzzles could be attached
|
|
20
|
+
* to a door OR placed in a room, which meant every consumer had to
|
|
21
|
+
* handle both, two validators had to agree about it, and a normaliser
|
|
22
|
+
* had to reconcile them; the comments record that fault family killing
|
|
23
|
+
* two consecutive generations. Being in a room is not a special case
|
|
24
|
+
* here, it is the only case.
|
|
25
|
+
*
|
|
26
|
+
* STATE IS EXACTLY ONE FIELD: `open`. Not solved-and-burned-and-locked;
|
|
27
|
+
* a thing is shut or it isn't. Everything else -- whether you may try,
|
|
28
|
+
* what it says when you get it wrong, what opening it does -- is
|
|
29
|
+
* derived from the kind and the config.
|
|
30
|
+
*
|
|
31
|
+
* A CODE ONLY BELONGS ON A PANEL. User ruling, verbatim: "if it's a
|
|
32
|
+
* _mechanical_ lock, it has a key or can be picked. You can't talk at a
|
|
33
|
+
* _mechanical_ lock." A 'lock' therefore opens by key or by force, and
|
|
34
|
+
* a 'ward' by the Art -- neither has anything to hear a phrase with.
|
|
35
|
+
* The migration enforces this by dropping the phrase off anything that
|
|
36
|
+
* isn't a panel.
|
|
37
|
+
*/
|
|
38
|
+
export class Device {
|
|
39
|
+
kind;
|
|
40
|
+
name;
|
|
41
|
+
description;
|
|
42
|
+
code;
|
|
43
|
+
keyItem;
|
|
44
|
+
grantsItem;
|
|
45
|
+
atSpot;
|
|
46
|
+
opensExit;
|
|
47
|
+
openMessage;
|
|
48
|
+
refuseMessage;
|
|
49
|
+
/** The whole of this device's state. */
|
|
50
|
+
open = false;
|
|
51
|
+
constructor(config) {
|
|
52
|
+
this.kind = config.kind;
|
|
53
|
+
this.name = config.name;
|
|
54
|
+
this.description = config.description;
|
|
55
|
+
// Enforced here as well as in the migration, because a generated
|
|
56
|
+
// seed can reach this constructor directly.
|
|
57
|
+
this.code = config.kind === 'panel' ? config.code : undefined;
|
|
58
|
+
this.keyItem = config.keyItem;
|
|
59
|
+
this.grantsItem = config.grantsItem;
|
|
60
|
+
this.atSpot = config.atSpot;
|
|
61
|
+
this.opensExit = config.opensExit;
|
|
62
|
+
this.openMessage = config.openMessage || 'It opens.';
|
|
63
|
+
this.refuseMessage = config.refuseMessage || `Nothing happens.`;
|
|
64
|
+
}
|
|
65
|
+
isOpen() {
|
|
66
|
+
return this.open;
|
|
67
|
+
}
|
|
68
|
+
/** Every verb that works this device, for telling the player exactly
|
|
69
|
+
* what they may type. */
|
|
70
|
+
verbs() {
|
|
71
|
+
return verbsFor(this.kind);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* OFFER a credential or a key to this device -- the deterministic
|
|
75
|
+
* route, from solve(). Succeeds when the code matches or the right
|
|
76
|
+
* item is in hand; a device with neither can only be forced.
|
|
77
|
+
*
|
|
78
|
+
* No prerequisite branch: `requiresPuzzle` is gone. A thing that
|
|
79
|
+
* needs something else to happen first is modelled by that something
|
|
80
|
+
* else -- a door that is locked, a person in the way -- not by a
|
|
81
|
+
* device refusing on behalf of a puzzle elsewhere.
|
|
82
|
+
*/
|
|
83
|
+
offer(providedAnswer, held) {
|
|
84
|
+
if (this.open) {
|
|
85
|
+
return { success: false, message: `${this.name} is already open.` };
|
|
86
|
+
}
|
|
87
|
+
const byKey = this.keyItem ? held.hasItem(this.keyItem.name) : false;
|
|
88
|
+
const byCode = matchesCredential(this.code, providedAnswer);
|
|
89
|
+
if (byKey || byCode) {
|
|
90
|
+
this.open = true;
|
|
91
|
+
return { success: true, message: this.openMessage };
|
|
92
|
+
}
|
|
93
|
+
return { success: false, message: this.refuseMessage };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* MAY this device be forced by the given verb -- the gate, from
|
|
97
|
+
* checkBypassGate(). Two of that method's four refusals are gone with
|
|
98
|
+
* the concepts behind them: 'locked' (no prerequisites) and 'burned'
|
|
99
|
+
* (no one-shot shortcut; a lock you failed to pick is a lock you can
|
|
100
|
+
* try again, which is what a lock is).
|
|
101
|
+
*/
|
|
102
|
+
canForce(verb) {
|
|
103
|
+
if (this.open) {
|
|
104
|
+
return { allowed: false, message: `${this.name} is already open.` };
|
|
105
|
+
}
|
|
106
|
+
if (!this.verbs().includes(verb)) {
|
|
107
|
+
return { allowed: false, message: this.wrongRouteMessage() };
|
|
108
|
+
}
|
|
109
|
+
return { allowed: true };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Apply an outcome decided elsewhere (a skill roll in the command).
|
|
113
|
+
* Assumes canForce() passed. No burn write -- failing to force a
|
|
114
|
+
* thing does not spend the thing.
|
|
115
|
+
*/
|
|
116
|
+
force(succeeded) {
|
|
117
|
+
if (succeeded) {
|
|
118
|
+
this.open = true;
|
|
119
|
+
return { success: true, message: this.openMessage, alarmed: false };
|
|
120
|
+
}
|
|
121
|
+
return { success: false, message: AFFORDANCE_FLAVOR[this.kind].failureMessage, alarmed: true };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The wrong-verb answer, in this device's own fiction -- keyed on what
|
|
125
|
+
* it IS, never on what was typed.
|
|
126
|
+
*/
|
|
127
|
+
wrongRouteMessage() {
|
|
128
|
+
const safeRoute = this.code
|
|
129
|
+
? `(The code itself always works, if you turn it up: "use ${this.name.toLowerCase()} <the code>".)`
|
|
130
|
+
: this.keyItem
|
|
131
|
+
? `(The right key opens it clean: "unlock" with ${this.keyItem.name} in hand.)`
|
|
132
|
+
: `(There's no code on this one -- force is the only way through.)`;
|
|
133
|
+
return `That finds no purchase here. ${AFFORDANCE_FLAVOR[this.kind].resists}\n${safeRoute}`;
|
|
134
|
+
}
|
|
135
|
+
/** The coaching line, behind the hints toggle. */
|
|
136
|
+
getHint() {
|
|
137
|
+
const text = hint(AFFORDANCE_FLAVOR[this.kind].hint);
|
|
138
|
+
return text.length > 0 ? text : undefined;
|
|
139
|
+
}
|
|
140
|
+
/** Persistence-only: one flag in, nothing out. */
|
|
141
|
+
restoreState(state) {
|
|
142
|
+
this.open = state.open;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/models/device.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
import { Logger } from '../utilities/logger.js';
|
|
2
2
|
import { Room } from './room.js';
|
|
3
|
-
import { Puzzle } from './puzzle.js';
|
|
4
3
|
import { AbstractDoor } from '../types/shared/abstracts.js';
|
|
5
4
|
export interface IDoorConstructorConfig {
|
|
6
5
|
roomA: Room;
|
|
7
6
|
roomB: Room;
|
|
8
7
|
isLocked?: boolean;
|
|
9
8
|
unlockItemOrSolution?: string;
|
|
10
|
-
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* WHICH DEVICE HOLDS THIS DOOR, and where that device stands.
|
|
12
|
+
*
|
|
13
|
+
* A Door is ONE object filed in BOTH rooms' exits maps, so a device in
|
|
14
|
+
* the chapel locks the same door a player standing in the crypt below
|
|
15
|
+
* is looking at -- with no device visible from their side. Without
|
|
16
|
+
* this, that player gets "the way up is locked" and nothing to act on:
|
|
17
|
+
* the dead-end refusal this codebase has spent four waves removing.
|
|
18
|
+
*
|
|
19
|
+
* Written ONCE, at wiring time (scene-factory step 4.9), and read by
|
|
20
|
+
* go.ts's refusal. Deliberately NOT a lookup across every room's
|
|
21
|
+
* devices at refusal time: that would be a second source of truth free
|
|
22
|
+
* to disagree with the lock itself, computed in the hot path of every
|
|
23
|
+
* failed move.
|
|
24
|
+
*/
|
|
25
|
+
export interface IDoorHolder {
|
|
26
|
+
/** The device's name, as the player would say it. */
|
|
27
|
+
device: string;
|
|
28
|
+
/** The room it physically stands in. */
|
|
29
|
+
room: string;
|
|
11
30
|
}
|
|
12
31
|
export declare class Door extends AbstractDoor {
|
|
13
32
|
name: string;
|
|
@@ -15,17 +34,17 @@ export declare class Door extends AbstractDoor {
|
|
|
15
34
|
roomB: Room;
|
|
16
35
|
isLocked: boolean;
|
|
17
36
|
unlockItemOrSolution?: string;
|
|
18
|
-
|
|
37
|
+
/** Set when a Device holds this door shut -- see IDoorHolder. */
|
|
38
|
+
heldBy?: IDoorHolder;
|
|
19
39
|
logger: Logger;
|
|
20
40
|
isLockable: boolean;
|
|
21
41
|
constructor(config: IDoorConstructorConfig);
|
|
22
42
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* wasn't already (a puzzle-guarded door starts locked by definition).
|
|
43
|
+
* Marks this door as held by a Device, and locks it. Called once at
|
|
44
|
+
* wiring time; the back-reference is what lets a refusal on EITHER
|
|
45
|
+
* side name where the mechanism actually is.
|
|
27
46
|
*/
|
|
28
|
-
|
|
47
|
+
heldByDevice(deviceName: string, roomName: string): void;
|
|
29
48
|
getOtherSide(currentRoom: Room): Room;
|
|
30
49
|
getOtherSideToName(currentRoom: Room): string;
|
|
31
50
|
attemptUnlock(itemOrSolution: string): boolean;
|
|
@@ -6,7 +6,8 @@ export class Door extends AbstractDoor {
|
|
|
6
6
|
roomB; // The other side of the door
|
|
7
7
|
isLocked;
|
|
8
8
|
unlockItemOrSolution;
|
|
9
|
-
|
|
9
|
+
/** Set when a Device holds this door shut -- see IDoorHolder. */
|
|
10
|
+
heldBy;
|
|
10
11
|
logger;
|
|
11
12
|
isLockable;
|
|
12
13
|
constructor(config) {
|
|
@@ -14,21 +15,25 @@ export class Door extends AbstractDoor {
|
|
|
14
15
|
this.roomA = config.roomA;
|
|
15
16
|
this.roomB = config.roomB;
|
|
16
17
|
this.name = `${this.roomA.name} <-> ${this.roomB.name}`;
|
|
17
|
-
|
|
18
|
+
// A door starts locked only if the seed says so, or if a key is
|
|
19
|
+
// required. It NO LONGER infers a locked start from carrying a
|
|
20
|
+
// puzzle -- there is no puzzle. A Device that opens this door locks
|
|
21
|
+
// it explicitly at wiring time (scene-factory step 4.9), and the
|
|
22
|
+
// golden test asserts that, because a dropped lock step fails
|
|
23
|
+
// silently: the hub's only gated content would simply stand open.
|
|
24
|
+
this.isLocked = config.isLocked || false;
|
|
18
25
|
this.unlockItemOrSolution = config.unlockItemOrSolution;
|
|
19
|
-
this.puzzle = config.puzzle;
|
|
20
26
|
this.logger = Logger.getInstance();
|
|
21
|
-
this.isLockable = !!config.unlockItemOrSolution
|
|
27
|
+
this.isLockable = !!config.unlockItemOrSolution;
|
|
22
28
|
this.logger.write(`Door created between ${this.roomA.name} and ${this.roomB.name}. Is Locked: ${this.isLocked}`);
|
|
23
29
|
}
|
|
24
30
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* wasn't already (a puzzle-guarded door starts locked by definition).
|
|
31
|
+
* Marks this door as held by a Device, and locks it. Called once at
|
|
32
|
+
* wiring time; the back-reference is what lets a refusal on EITHER
|
|
33
|
+
* side name where the mechanism actually is.
|
|
29
34
|
*/
|
|
30
|
-
|
|
31
|
-
this.
|
|
35
|
+
heldByDevice(deviceName, roomName) {
|
|
36
|
+
this.heldBy = { device: deviceName, room: roomName };
|
|
32
37
|
this.isLocked = true;
|
|
33
38
|
this.isLockable = true;
|
|
34
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"door.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/models/door.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"door.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/models/door.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AA+B5D,MAAM,OAAO,IAAK,SAAQ,YAAY;IACpC,IAAI,CAAS;IACb,KAAK,CAAO,CAAE,uBAAuB;IACrC,KAAK,CAAO,CAAE,6BAA6B;IAC3C,QAAQ,CAAU;IAClB,oBAAoB,CAAU;IAC9B,iEAAiE;IACjE,MAAM,CAAe;IACrB,MAAM,CAAS;IACf,UAAU,CAAS;IAEnB,YAAY,MAA8B;QACxC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACxD,gEAAgE;QAChE,+DAA+D;QAC/D,oEAAoE;QACpE,iEAAiE;QACjE,8DAA8D;QAC9D,kEAAkE;QAClE,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC;QACzC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC,oBAAoB,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC;QAEhD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,gBAAgB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnH,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,UAAkB,EAAE,QAAgB;QAC/C,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACrD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,YAAY,CAAC,WAAiB;QAC5B,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IAChE,CAAC;IAED,kBAAkB,CAAC,WAAiB;QAClC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1F,CAAC;IAED,aAAa,CAAC,cAAsB;QAClC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,oBAAoB,KAAK,cAAc,EAAE,CAAC;YAC/F,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,IAAI,CAAC,IAAI,WAAW,cAAc,EAAE,CAAC,CAAC;YAC1E,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,IAAI,WAAW,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -8,6 +8,87 @@ export interface INPCConstructorConfig {
|
|
|
8
8
|
description: string;
|
|
9
9
|
playerConstructorConfig: IPlayerConstructorConfig;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* One barrier as the prompt needs to see it.
|
|
13
|
+
*
|
|
14
|
+
* STRUCTURAL on purpose, and that is the entire reason this interface
|
|
15
|
+
* exists rather than the functions below taking a `Puzzle`. The
|
|
16
|
+
* puzzle/solve mechanic is being replaced by a `Device` model, and these
|
|
17
|
+
* two functions are the last thing standing between an NPC and inventing
|
|
18
|
+
* a door code. Typing them over a SHAPE rather than a class means the
|
|
19
|
+
* type swap is a change of adapter at one call site, with these
|
|
20
|
+
* functions and their tests untouched -- so "the rewrite preserved the
|
|
21
|
+
* behaviour" becomes something the suite proves rather than something we
|
|
22
|
+
* hope.
|
|
23
|
+
*
|
|
24
|
+
* `description` is optional and interpolated raw, which preserves an
|
|
25
|
+
* existing wart exactly: a barrier with no description renders the
|
|
26
|
+
* literal string "undefined" into the prompt today. Recorded rather than
|
|
27
|
+
* fixed, because this extraction is behaviour-preserving by contract and
|
|
28
|
+
* a silent improvement here would make the swap unprovable.
|
|
29
|
+
*
|
|
30
|
+
* `sealingDirection` is a plain string so this pair depends on nothing:
|
|
31
|
+
* a `Direction` is assignable to it, and the functions stay importable
|
|
32
|
+
* from anywhere.
|
|
33
|
+
*/
|
|
34
|
+
export interface IBarrierPost {
|
|
35
|
+
name: string;
|
|
36
|
+
/**
|
|
37
|
+
* MANDATORY, as of the Device flip. It was optional while Puzzle fed
|
|
38
|
+
* this interface (a riddle genuinely could be absent), and the cost
|
|
39
|
+
* was that barrierPostNote interpolated it raw and rendered the
|
|
40
|
+
* literal string "undefined" into an NPC's prompt. Device cannot be
|
|
41
|
+
* constructed without a description, so that branch is DEAD rather
|
|
42
|
+
* than guarded -- a deletion, not a fix.
|
|
43
|
+
*/
|
|
44
|
+
description: string;
|
|
45
|
+
/** The credential that opens it. Absent means even its keeper doesn't know. */
|
|
46
|
+
code?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The item that opens it outright, if one exists. Present ONLY so the
|
|
49
|
+
* brief can stop asserting "no key" about a lock that takes exactly
|
|
50
|
+
* one key -- see the note in barrierPostNote. A plain string, like
|
|
51
|
+
* sealingDirection, so this pair keeps depending on nothing.
|
|
52
|
+
*/
|
|
53
|
+
keyItem?: string;
|
|
54
|
+
open: boolean;
|
|
55
|
+
/** Set only when this barrier seals an EXIT rather than sitting in the room. */
|
|
56
|
+
sealingDirection?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* BARRIERS AT YOUR POST (a real session: a beaten sentry announced he
|
|
60
|
+
* was "unlocking" a spell-sealed hatch he could never open -- his AI had
|
|
61
|
+
* no idea what guarded his own door, tried a doomed "unlock", and
|
|
62
|
+
* claimed success). An NPC standing at a barrier knows what seals it,
|
|
63
|
+
* that he cannot wish it open, and HOW it opens -- as a guarded secret,
|
|
64
|
+
* so coercion and bribery become a real path to the pass.
|
|
65
|
+
*
|
|
66
|
+
* The CALLER decides whose barriers these are. Companions get an empty
|
|
67
|
+
* list: a bound spirit that knew the code would simply hand it to its
|
|
68
|
+
* master and skip the barrier entirely.
|
|
69
|
+
*
|
|
70
|
+
* Exported and pure for the reason the note below is: it fails SILENTLY.
|
|
71
|
+
* Nothing throws when this stops handing over the real pass -- the NPC
|
|
72
|
+
* just starts inventing one, and the only detector is a player three
|
|
73
|
+
* rooms away typing a code that was never real.
|
|
74
|
+
*/
|
|
75
|
+
export declare function barrierPostNote(barriers: IBarrierPost[]): string;
|
|
76
|
+
/**
|
|
77
|
+
* How many real credentials this NPC was actually handed -- the number
|
|
78
|
+
* credentialHonestyNote turns into "you know the pass for the barrier at
|
|
79
|
+
* your own post, and NO others" versus "you hold NONE".
|
|
80
|
+
*
|
|
81
|
+
* A barrier only counts if it is SHUT and has a code. An open one is
|
|
82
|
+
* nothing to guard, and one with no code is a secret its own keeper
|
|
83
|
+
* doesn't have.
|
|
84
|
+
*
|
|
85
|
+
* It counts DEVICES only. A guard once carried a passphrase of their
|
|
86
|
+
* own and it was counted here; the user removed the concept
|
|
87
|
+
* (2026-08-27) because the way past a person is social or violent, and
|
|
88
|
+
* because a guard's phrase had no clue guarantee behind it -- see the
|
|
89
|
+
* note where Player.passphrase used to be.
|
|
90
|
+
*/
|
|
91
|
+
export declare function passesHeldBy(barriers: IBarrierPost[]): number;
|
|
11
92
|
/**
|
|
12
93
|
* THE CAST PIN -- geographySummary's missing twin. See the note at its
|
|
13
94
|
* call site in respondTo(). Exported and PURE for the same reason as
|
|
@@ -30,6 +111,68 @@ export declare function castPin(names: string[]): string;
|
|
|
30
111
|
* notice.
|
|
31
112
|
*/
|
|
32
113
|
export declare function credentialHonestyNote(passesHeld: number): string;
|
|
114
|
+
/**
|
|
115
|
+
* WHAT YOU KNOW ENDS AT THIS ROOM -- audit findings #9 and #10, the last
|
|
116
|
+
* two unpinned facts from the credential sweep, and the same shape as
|
|
117
|
+
* the credential hole: pinned for the NPC's own room, invented for
|
|
118
|
+
* anywhere else.
|
|
119
|
+
*
|
|
120
|
+
* #9 an NPC asked where something is names a REAL room the item is
|
|
121
|
+
* not in. Real, because geography is pinned -- which makes it
|
|
122
|
+
* worse, not better. A vague answer costs a player nothing; a
|
|
123
|
+
* plausible, checkable, wrong one costs them the walk there, the
|
|
124
|
+
* search, and their trust in the next true thing they hear.
|
|
125
|
+
* #10 an NPC asked what a door ELSEWHERE needs invents a requirement.
|
|
126
|
+
* They only ever see their own room's exits.
|
|
127
|
+
*
|
|
128
|
+
* Deliberately NOT an index of the world's items and doors: that would
|
|
129
|
+
* spoil the game and cost prompt budget to do it. Pin what the NPC can
|
|
130
|
+
* legitimately know, deny the rest, index nothing.
|
|
131
|
+
*
|
|
132
|
+
* The scoping matters and is the whole difficulty. An NPC absolutely may
|
|
133
|
+
* say where things are when they were TOLD -- the client's briefing, the
|
|
134
|
+
* legwork facts ask.ts hands over, their own scripted talking points are
|
|
135
|
+
* all real knowledge, engine-supplied, and a blanket denial would gag
|
|
136
|
+
* the Johnson mid-brief. What is banned is GUESSING TO BE HELPFUL, which
|
|
137
|
+
* is the specific thing a model does when it has no answer and wants to
|
|
138
|
+
* give one.
|
|
139
|
+
*/
|
|
140
|
+
export declare function localKnowledgeNote(roomName?: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* OUT-OF-CHARACTER LEAKAGE on the exposition channel.
|
|
143
|
+
*
|
|
144
|
+
* Playtest 2026-08-27 (Sherry): "The response from Mr. Krow was OOC" --
|
|
145
|
+
* Krow answered in the game's own voice instead of in his.
|
|
146
|
+
*
|
|
147
|
+
* This is the SAME SEAM as splitSpokenLines, one layer up, and widening
|
|
148
|
+
* it was the right move rather than building a second mechanism. The
|
|
149
|
+
* exposition channel is the only place a model's non-fiction voice can
|
|
150
|
+
* reach the screen: `say` lines are attributed dialogue and [COMMAND]
|
|
151
|
+
* lines are parsed, so anything that is neither prints as narration in
|
|
152
|
+
* narration blue. A filter for exactly this already existed and was
|
|
153
|
+
* built from ONE report -- the first-person director ("I'll have Deacon
|
|
154
|
+
* Ruy stay guarded but crack slightly under the pressure...") -- so it
|
|
155
|
+
* only ever matched that one shape.
|
|
156
|
+
*
|
|
157
|
+
* The shapes it missed are the ordinary ones: the assistant preamble
|
|
158
|
+
* ("Certainly! Here's how he responds"), the frame ("As Mr. Krow, I'd
|
|
159
|
+
* say..."), the explicit marker ("OOC:", "Note:"), and talk about the
|
|
160
|
+
* player rather than to them ("The player is trying to...").
|
|
161
|
+
*
|
|
162
|
+
* SUPPRESSED, not restyled. The player also asked for OOC to be visibly
|
|
163
|
+
* distinct from fiction, and that is a real and separate feature -- but
|
|
164
|
+
* "Certainly! Here's what he'd say" is not out-of-character INFORMATION,
|
|
165
|
+
* it is the model failing to stay in the fiction, and there is nothing
|
|
166
|
+
* in it worth showing in any colour. The genuine OOC channels
|
|
167
|
+
* (logger.meta for mechanics, hint() for coaching) already exist and are
|
|
168
|
+
* already visibly distinct; routing leakage into them would fill the
|
|
169
|
+
* player's straight-talk channel with noise.
|
|
170
|
+
*
|
|
171
|
+
* Exported and PURE because it fails silently in the usual way: nothing
|
|
172
|
+
* throws when a pattern stops matching, the line just prints, and the
|
|
173
|
+
* only detector is a player watching their fixer break character.
|
|
174
|
+
*/
|
|
175
|
+
export declare function isOutOfCharacter(line: string, npcName?: string): boolean;
|
|
33
176
|
/**
|
|
34
177
|
* SPEECH REPAIR: turns a model reply's raw lines into lines the
|
|
35
178
|
* classifier below can actually read. Exported and PURE so the rules
|