@sharpee/transcript-tester 0.9.62-beta → 0.9.66-beta

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 (157) hide show
  1. package/cli.d.ts.map +1 -0
  2. package/cli.js.map +1 -0
  3. package/condition-evaluator.d.ts.map +1 -0
  4. package/condition-evaluator.js.map +1 -0
  5. package/{dist-esm/fast-cli.d.ts → fast-cli.d.ts} +1 -1
  6. package/fast-cli.d.ts.map +1 -0
  7. package/{dist/fast-cli.js → fast-cli.js} +1 -1
  8. package/fast-cli.js.map +1 -0
  9. package/index.d.ts.map +1 -0
  10. package/index.js.map +1 -0
  11. package/navigator.d.ts.map +1 -0
  12. package/navigator.js.map +1 -0
  13. package/package.json +17 -27
  14. package/parser.d.ts.map +1 -0
  15. package/parser.js.map +1 -0
  16. package/reporter.d.ts.map +1 -0
  17. package/reporter.js.map +1 -0
  18. package/runner.d.ts.map +1 -0
  19. package/runner.js.map +1 -0
  20. package/{dist/story-loader.d.ts → story-loader.d.ts} +2 -2
  21. package/story-loader.d.ts.map +1 -0
  22. package/{dist-npm/story-loader.js → story-loader.js} +5 -5
  23. package/story-loader.js.map +1 -0
  24. package/types.d.ts.map +1 -0
  25. package/types.js.map +1 -0
  26. package/.turbo/turbo-build.log +0 -4
  27. package/LICENSE +0 -21
  28. package/dist/cli.d.ts +0 -11
  29. package/dist/cli.d.ts.map +0 -1
  30. package/dist/cli.js +0 -367
  31. package/dist/cli.js.map +0 -1
  32. package/dist/condition-evaluator.d.ts +0 -30
  33. package/dist/condition-evaluator.d.ts.map +0 -1
  34. package/dist/condition-evaluator.js +0 -314
  35. package/dist/condition-evaluator.js.map +0 -1
  36. package/dist/fast-cli.d.ts +0 -13
  37. package/dist/fast-cli.d.ts.map +0 -1
  38. package/dist/fast-cli.js.map +0 -1
  39. package/dist/index.d.ts +0 -17
  40. package/dist/index.d.ts.map +0 -1
  41. package/dist/index.js +0 -48
  42. package/dist/index.js.map +0 -1
  43. package/dist/navigator.d.ts +0 -27
  44. package/dist/navigator.d.ts.map +0 -1
  45. package/dist/navigator.js +0 -303
  46. package/dist/navigator.js.map +0 -1
  47. package/dist/parser.d.ts +0 -19
  48. package/dist/parser.d.ts.map +0 -1
  49. package/dist/parser.js +0 -453
  50. package/dist/parser.js.map +0 -1
  51. package/dist/reporter.d.ts +0 -41
  52. package/dist/reporter.d.ts.map +0 -1
  53. package/dist/reporter.js +0 -386
  54. package/dist/reporter.js.map +0 -1
  55. package/dist/runner.d.ts +0 -44
  56. package/dist/runner.d.ts.map +0 -1
  57. package/dist/runner.js +0 -977
  58. package/dist/runner.js.map +0 -1
  59. package/dist/story-loader.d.ts.map +0 -1
  60. package/dist/story-loader.js +0 -169
  61. package/dist/story-loader.js.map +0 -1
  62. package/dist/types.d.ts +0 -204
  63. package/dist/types.d.ts.map +0 -1
  64. package/dist/types.js +0 -8
  65. package/dist/types.js.map +0 -1
  66. package/dist-esm/cli.d.ts.map +0 -1
  67. package/dist-esm/cli.js +0 -332
  68. package/dist-esm/cli.js.map +0 -1
  69. package/dist-esm/condition-evaluator.d.ts.map +0 -1
  70. package/dist-esm/condition-evaluator.js +0 -311
  71. package/dist-esm/condition-evaluator.js.map +0 -1
  72. package/dist-esm/fast-cli.d.ts.map +0 -1
  73. package/dist-esm/fast-cli.js +0 -328
  74. package/dist-esm/fast-cli.js.map +0 -1
  75. package/dist-esm/index.d.ts.map +0 -1
  76. package/dist-esm/index.js +0 -21
  77. package/dist-esm/index.js.map +0 -1
  78. package/dist-esm/navigator.d.ts.map +0 -1
  79. package/dist-esm/navigator.js +0 -300
  80. package/dist-esm/navigator.js.map +0 -1
  81. package/dist-esm/parser.d.ts.map +0 -1
  82. package/dist-esm/parser.js +0 -415
  83. package/dist-esm/parser.js.map +0 -1
  84. package/dist-esm/reporter.d.ts.map +0 -1
  85. package/dist-esm/reporter.js +0 -342
  86. package/dist-esm/reporter.js.map +0 -1
  87. package/dist-esm/runner.d.ts.map +0 -1
  88. package/dist-esm/runner.js +0 -941
  89. package/dist-esm/runner.js.map +0 -1
  90. package/dist-esm/story-loader.d.ts +0 -31
  91. package/dist-esm/story-loader.d.ts.map +0 -1
  92. package/dist-esm/story-loader.js +0 -131
  93. package/dist-esm/story-loader.js.map +0 -1
  94. package/dist-esm/types.d.ts.map +0 -1
  95. package/dist-esm/types.js +0 -7
  96. package/dist-esm/types.js.map +0 -1
  97. package/dist-npm/cli.d.ts +0 -11
  98. package/dist-npm/cli.d.ts.map +0 -1
  99. package/dist-npm/cli.js.map +0 -1
  100. package/dist-npm/condition-evaluator.d.ts +0 -30
  101. package/dist-npm/condition-evaluator.d.ts.map +0 -1
  102. package/dist-npm/condition-evaluator.js.map +0 -1
  103. package/dist-npm/fast-cli.d.ts +0 -13
  104. package/dist-npm/fast-cli.d.ts.map +0 -1
  105. package/dist-npm/fast-cli.js +0 -363
  106. package/dist-npm/fast-cli.js.map +0 -1
  107. package/dist-npm/index.d.ts +0 -17
  108. package/dist-npm/index.d.ts.map +0 -1
  109. package/dist-npm/index.js.map +0 -1
  110. package/dist-npm/navigator.d.ts +0 -27
  111. package/dist-npm/navigator.d.ts.map +0 -1
  112. package/dist-npm/navigator.js.map +0 -1
  113. package/dist-npm/parser.d.ts +0 -19
  114. package/dist-npm/parser.d.ts.map +0 -1
  115. package/dist-npm/parser.js.map +0 -1
  116. package/dist-npm/reporter.d.ts +0 -41
  117. package/dist-npm/reporter.d.ts.map +0 -1
  118. package/dist-npm/reporter.js.map +0 -1
  119. package/dist-npm/runner.d.ts +0 -44
  120. package/dist-npm/runner.d.ts.map +0 -1
  121. package/dist-npm/runner.js.map +0 -1
  122. package/dist-npm/story-loader.d.ts +0 -31
  123. package/dist-npm/story-loader.d.ts.map +0 -1
  124. package/dist-npm/story-loader.js.map +0 -1
  125. package/dist-npm/types.d.ts +0 -204
  126. package/dist-npm/types.d.ts.map +0 -1
  127. package/dist-npm/types.js.map +0 -1
  128. package/src/cli.ts +0 -385
  129. package/src/condition-evaluator.ts +0 -382
  130. package/src/fast-cli.ts +0 -403
  131. package/src/index.ts +0 -26
  132. package/src/navigator.ts +0 -365
  133. package/src/parser.ts +0 -488
  134. package/src/reporter.ts +0 -409
  135. package/src/runner.ts +0 -1152
  136. package/src/story-loader.ts +0 -168
  137. package/src/types.ts +0 -244
  138. package/tsconfig.esm.json +0 -11
  139. package/tsconfig.esm.tsbuildinfo +0 -1
  140. package/tsconfig.json +0 -22
  141. package/tsconfig.tsbuildinfo +0 -1
  142. /package/{dist-esm/cli.d.ts → cli.d.ts} +0 -0
  143. /package/{dist-npm/cli.js → cli.js} +0 -0
  144. /package/{dist-esm/condition-evaluator.d.ts → condition-evaluator.d.ts} +0 -0
  145. /package/{dist-npm/condition-evaluator.js → condition-evaluator.js} +0 -0
  146. /package/{dist-esm/index.d.ts → index.d.ts} +0 -0
  147. /package/{dist-npm/index.js → index.js} +0 -0
  148. /package/{dist-esm/navigator.d.ts → navigator.d.ts} +0 -0
  149. /package/{dist-npm/navigator.js → navigator.js} +0 -0
  150. /package/{dist-esm/parser.d.ts → parser.d.ts} +0 -0
  151. /package/{dist-npm/parser.js → parser.js} +0 -0
  152. /package/{dist-esm/reporter.d.ts → reporter.d.ts} +0 -0
  153. /package/{dist-npm/reporter.js → reporter.js} +0 -0
  154. /package/{dist-esm/runner.d.ts → runner.d.ts} +0 -0
  155. /package/{dist-npm/runner.js → runner.js} +0 -0
  156. /package/{dist-esm/types.d.ts → types.d.ts} +0 -0
  157. /package/{dist-npm/types.js → types.js} +0 -0
package/dist-esm/cli.js DELETED
@@ -1,332 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Transcript Tester CLI
4
- *
5
- * Usage:
6
- * transcript-test <story-path> [transcript-files...]
7
- * transcript-test <story-path> --all
8
- * transcript-test <story-path> --verbose
9
- */
10
- import * as path from 'path';
11
- import * as fs from 'fs';
12
- import * as readline from 'readline';
13
- import { parseTranscriptFile, validateTranscript } from './parser';
14
- import { runTranscript } from './runner';
15
- import { reportTranscript, reportTestRun, getExitCode, generateTimestamp, writeResultsToJson, writeReportToFile } from './reporter';
16
- import { loadStory, findTranscripts } from './story-loader';
17
- /**
18
- * Parse command line arguments
19
- */
20
- function parseArgs(args) {
21
- const options = {
22
- storyPath: '',
23
- transcriptPaths: [],
24
- verbose: false,
25
- stopOnFailure: false,
26
- all: false,
27
- chain: false,
28
- outputDir: null,
29
- play: false
30
- };
31
- let i = 0;
32
- while (i < args.length) {
33
- const arg = args[i];
34
- if (arg === '--verbose' || arg === '-v') {
35
- options.verbose = true;
36
- }
37
- else if (arg === '--stop-on-failure' || arg === '-s') {
38
- options.stopOnFailure = true;
39
- }
40
- else if (arg === '--all' || arg === '-a') {
41
- options.all = true;
42
- }
43
- else if (arg === '--chain' || arg === '-c') {
44
- options.chain = true;
45
- }
46
- else if (arg === '--play' || arg === '-p') {
47
- options.play = true;
48
- }
49
- else if (arg === '--output-dir' || arg === '-o') {
50
- i++;
51
- if (i < args.length) {
52
- options.outputDir = args[i];
53
- }
54
- }
55
- else if (arg === '--help' || arg === '-h') {
56
- printHelp();
57
- process.exit(0);
58
- }
59
- else if (!arg.startsWith('-')) {
60
- if (!options.storyPath) {
61
- options.storyPath = arg;
62
- }
63
- else {
64
- options.transcriptPaths.push(arg);
65
- }
66
- }
67
- i++;
68
- }
69
- return options;
70
- }
71
- /**
72
- * Print help message
73
- */
74
- function printHelp() {
75
- console.log(`
76
- Transcript Tester - Test Sharpee stories with transcript files
77
-
78
- Usage:
79
- transcript-test <story-path> [transcript-files...] [options]
80
- transcript-test <story-path> --play
81
-
82
- Arguments:
83
- story-path Path to the story directory (e.g., stories/dungeo)
84
- transcript-files One or more .transcript files to run
85
-
86
- Options:
87
- -p, --play Interactive play mode (REPL)
88
- -a, --all Run all transcripts in the story's tests/ directory
89
- -c, --chain Chain transcripts (don't reset game state between them)
90
- -v, --verbose Show detailed output for each command
91
- -s, --stop-on-failure Stop on first failure
92
- -o, --output-dir <dir> Write timestamped results to directory (JSON + text report)
93
- -h, --help Show this help message
94
-
95
- Examples:
96
- transcript-test stories/dungeo --play
97
- transcript-test stories/dungeo tests/navigation.transcript
98
- transcript-test stories/dungeo --all
99
- transcript-test stories/dungeo tests/*.transcript --verbose
100
- transcript-test stories/dungeo --all -o test-results
101
- transcript-test stories/dungeo --chain tests/setup.transcript tests/puzzle.transcript
102
- `);
103
- }
104
- /**
105
- * Run interactive play mode (REPL)
106
- */
107
- async function runInteractiveMode(game) {
108
- const rl = readline.createInterface({
109
- input: process.stdin,
110
- output: process.stdout
111
- });
112
- let debugMode = false;
113
- let traceMode = false;
114
- console.log('\n--- Interactive Mode ---');
115
- console.log('Type commands to play. Special commands:');
116
- console.log(' /quit, /q - Exit the game');
117
- console.log(' /debug - Toggle debug mode (show events after each command)');
118
- console.log(' /trace - Toggle parser trace mode (show grammar matching)');
119
- console.log(' /events - Show events from last command');
120
- console.log(' /look, /l - Shortcut for "look"');
121
- console.log(' /inv, /i - Shortcut for "inventory"');
122
- console.log('');
123
- // Show initial room description
124
- const initialOutput = await game.executeCommand('look');
125
- console.log(initialOutput);
126
- const prompt = () => {
127
- rl.question('\n> ', async (input) => {
128
- const trimmed = input.trim();
129
- if (!trimmed) {
130
- prompt();
131
- return;
132
- }
133
- // Handle special commands
134
- if (trimmed === '/quit' || trimmed === '/q') {
135
- console.log('Goodbye!');
136
- rl.close();
137
- process.exit(0);
138
- return;
139
- }
140
- if (trimmed === '/restart') {
141
- console.log('(Restart not yet implemented - please exit and rerun)');
142
- prompt();
143
- return;
144
- }
145
- if (trimmed === '/debug') {
146
- debugMode = !debugMode;
147
- console.log(`Debug mode: ${debugMode ? 'ON' : 'OFF'}`);
148
- prompt();
149
- return;
150
- }
151
- if (trimmed === '/trace') {
152
- traceMode = !traceMode;
153
- process.env.PARSER_DEBUG = traceMode ? 'true' : '';
154
- console.log(`Parser trace: ${traceMode ? 'ON' : 'OFF'}`);
155
- prompt();
156
- return;
157
- }
158
- if (trimmed === '/events') {
159
- if (game.lastEvents && game.lastEvents.length > 0) {
160
- console.log('\nEvents from last command:');
161
- for (const event of game.lastEvents) {
162
- console.log(` ${event.type}`);
163
- if (event.data && Object.keys(event.data).length > 0) {
164
- console.log(` ${JSON.stringify(event.data)}`);
165
- }
166
- }
167
- }
168
- else {
169
- console.log('(No events from last command)');
170
- }
171
- prompt();
172
- return;
173
- }
174
- // Shortcuts
175
- let command = trimmed;
176
- if (trimmed === '/look' || trimmed === '/l') {
177
- command = 'look';
178
- }
179
- else if (trimmed === '/inv' || trimmed === '/i') {
180
- command = 'inventory';
181
- }
182
- // Execute the command
183
- try {
184
- const output = await game.executeCommand(command);
185
- console.log(output);
186
- // Show events in debug mode
187
- if (debugMode && game.lastEvents && game.lastEvents.length > 0) {
188
- console.log('\n[Events]');
189
- for (const event of game.lastEvents) {
190
- const data = event.data && Object.keys(event.data).length > 0
191
- ? ` ${JSON.stringify(event.data)}`
192
- : '';
193
- console.log(` ${event.type}${data}`);
194
- }
195
- }
196
- }
197
- catch (error) {
198
- console.error(`Error: ${error instanceof Error ? error.message : error}`);
199
- }
200
- prompt();
201
- });
202
- };
203
- prompt();
204
- }
205
- /**
206
- * Main entry point
207
- */
208
- async function main() {
209
- const args = process.argv.slice(2);
210
- if (args.length === 0) {
211
- printHelp();
212
- process.exit(1);
213
- }
214
- const options = parseArgs(args);
215
- if (!options.storyPath) {
216
- console.error('Error: Story path is required');
217
- printHelp();
218
- process.exit(1);
219
- }
220
- // Interactive play mode
221
- if (options.play) {
222
- console.log(`Loading story from: ${options.storyPath}`);
223
- let game;
224
- try {
225
- game = await loadStory(options.storyPath);
226
- }
227
- catch (error) {
228
- console.error(`Error loading story: ${error}`);
229
- process.exit(3);
230
- }
231
- await runInteractiveMode(game);
232
- return;
233
- }
234
- // Find transcript files
235
- let transcriptPaths = options.transcriptPaths;
236
- if (options.all || transcriptPaths.length === 0) {
237
- const testsDir = path.join(options.storyPath, 'tests');
238
- if (fs.existsSync(testsDir)) {
239
- transcriptPaths = findTranscripts(testsDir);
240
- }
241
- else {
242
- // Check for transcripts directory
243
- const transcriptsDir = path.join(options.storyPath, 'tests', 'transcripts');
244
- if (fs.existsSync(transcriptsDir)) {
245
- transcriptPaths = findTranscripts(transcriptsDir);
246
- }
247
- }
248
- }
249
- // Deduplicate paths
250
- transcriptPaths = [...new Set(transcriptPaths)];
251
- if (transcriptPaths.length === 0) {
252
- console.error('Error: No transcript files found');
253
- console.error(`Looked in: ${path.join(options.storyPath, 'tests')}`);
254
- process.exit(2);
255
- }
256
- console.log(`Loading story from: ${options.storyPath}`);
257
- // Load the story
258
- let game;
259
- try {
260
- game = await loadStory(options.storyPath);
261
- }
262
- catch (error) {
263
- console.error(`Error loading story: ${error}`);
264
- process.exit(3);
265
- }
266
- console.log(`Found ${transcriptPaths.length} transcript(s) to run`);
267
- if (options.chain) {
268
- console.log(`Chain mode: Game state will persist between transcripts`);
269
- }
270
- // Run all transcripts
271
- const results = [];
272
- for (const transcriptPath of transcriptPaths) {
273
- // Parse the transcript
274
- const transcript = parseTranscriptFile(transcriptPath);
275
- // Validate
276
- const errors = validateTranscript(transcript);
277
- if (errors.length > 0) {
278
- console.error(`\nErrors in ${transcriptPath}:`);
279
- for (const err of errors) {
280
- console.error(` - ${err}`);
281
- }
282
- continue;
283
- }
284
- // Reload story for each transcript to reset state (unless chaining)
285
- if (!options.chain) {
286
- game = await loadStory(options.storyPath);
287
- }
288
- // Run the transcript
289
- const result = await runTranscript(transcript, game, {
290
- verbose: options.verbose,
291
- stopOnFailure: options.stopOnFailure
292
- });
293
- results.push(result);
294
- // Report individual transcript results
295
- reportTranscript(result, { verbose: options.verbose });
296
- // Stop if requested and there was a failure
297
- if (options.stopOnFailure && result.failed > 0) {
298
- break;
299
- }
300
- }
301
- // Aggregate results
302
- const runResult = {
303
- transcripts: results,
304
- totalPassed: results.reduce((sum, r) => sum + r.passed, 0),
305
- totalFailed: results.reduce((sum, r) => sum + r.failed, 0),
306
- totalExpectedFailures: results.reduce((sum, r) => sum + r.expectedFailures, 0),
307
- totalSkipped: results.reduce((sum, r) => sum + r.skipped, 0),
308
- totalDuration: results.reduce((sum, r) => sum + r.duration, 0)
309
- };
310
- // Final report if multiple transcripts
311
- if (results.length > 1) {
312
- reportTestRun(runResult, { verbose: options.verbose });
313
- }
314
- // Write results to files if output directory specified
315
- if (options.outputDir) {
316
- const timestamp = generateTimestamp();
317
- const jsonPath = writeResultsToJson(runResult, options.outputDir, timestamp);
318
- const reportPath = writeReportToFile(runResult, options.outputDir, timestamp);
319
- console.log();
320
- console.log(`Results written to:`);
321
- console.log(` JSON: ${jsonPath}`);
322
- console.log(` Report: ${reportPath}`);
323
- }
324
- // Exit with appropriate code
325
- process.exit(getExitCode(runResult));
326
- }
327
- // Run
328
- main().catch(error => {
329
- console.error('Fatal error:', error);
330
- process.exit(1);
331
- });
332
- //# sourceMappingURL=cli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"condition-evaluator.d.ts","sourceRoot":"","sources":["../src/condition-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,UAAU,cAAc;IACtB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC7C,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,GAAG,EAAE,CAAC;IAC7E,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,GAAG,GAAG,EAAE,CAAC;IACtD,cAAc,IAAI,GAAG,EAAE,CAAC;CACzB;AAsHD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,GACf,eAAe,CA+BjB"}
@@ -1,311 +0,0 @@
1
- /**
2
- * Condition Evaluator for Smart Transcript Directives (ADR-092)
3
- *
4
- * Evaluates condition expressions against game state.
5
- *
6
- * Supported expressions:
7
- * - location = "Room Name" - Player is in room with that name
8
- * - room contains "entity" - Entity with that name is in current room
9
- * - inventory contains "item" - Player has item with that name
10
- * - not inventory contains "item" - Player does NOT have item
11
- * - entity "X" exists - Entity with name X exists anywhere
12
- * - entity "X" alive - NPC entity is not dead
13
- * - entity "X" in "Room" - Entity X is in specified room
14
- */
15
- /**
16
- * Find an entity by name (searches identity.name and aliases)
17
- * Prioritizes exact matches and actors/NPCs over rooms
18
- */
19
- function findEntityByName(world, name) {
20
- const nameLower = name.toLowerCase();
21
- const allMatches = world.findWhere((entity) => {
22
- const identity = entity.get?.('identity') || entity.traits?.get?.('identity');
23
- if (!identity)
24
- return false;
25
- const entityName = (identity.name || '').toLowerCase();
26
- const aliases = (identity.aliases || []).map((a) => a.toLowerCase());
27
- return entityName === nameLower ||
28
- entityName.includes(nameLower) ||
29
- aliases.some((a) => a === nameLower || a.includes(nameLower));
30
- });
31
- if (allMatches.length === 0)
32
- return null;
33
- // Prioritize: 1) exact name match, 2) exact alias match, 3) actors/NPCs, 4) first match
34
- const exactNameMatch = allMatches.find((e) => {
35
- const identity = e.get?.('identity') || e.traits?.get?.('identity');
36
- return (identity?.name || '').toLowerCase() === nameLower;
37
- });
38
- if (exactNameMatch)
39
- return exactNameMatch;
40
- const exactAliasMatch = allMatches.find((e) => {
41
- const identity = e.get?.('identity') || e.traits?.get?.('identity');
42
- const aliases = (identity?.aliases || []).map((a) => a.toLowerCase());
43
- return aliases.includes(nameLower);
44
- });
45
- if (exactAliasMatch)
46
- return exactAliasMatch;
47
- // Prefer actors/NPCs/combatants over rooms
48
- const actorMatch = allMatches.find((e) => e.get?.('actor') || e.get?.('npc') || e.get?.('combatant') ||
49
- e.traits?.get?.('actor') || e.traits?.get?.('npc') || e.traits?.get?.('combatant'));
50
- if (actorMatch)
51
- return actorMatch;
52
- return allMatches[0];
53
- }
54
- /**
55
- * Find a room by name
56
- */
57
- function findRoomByName(world, name) {
58
- const nameLower = name.toLowerCase();
59
- const rooms = world.findWhere((entity) => {
60
- // Check if it's a room
61
- const roomTrait = entity.get?.('room') || entity.traits?.get?.('room');
62
- if (!roomTrait)
63
- return false;
64
- const identity = entity.get?.('identity') || entity.traits?.get?.('identity');
65
- if (!identity)
66
- return false;
67
- const entityName = (identity.name || '').toLowerCase();
68
- return entityName === nameLower || entityName.includes(nameLower);
69
- });
70
- return rooms[0] || null;
71
- }
72
- /**
73
- * Get player entity
74
- */
75
- function getPlayer(world) {
76
- const players = world.findWhere((entity) => {
77
- const identity = entity.get?.('identity') || entity.traits?.get?.('identity');
78
- return identity?.name === 'player' || identity?.name === 'yourself';
79
- });
80
- return players[0] || null;
81
- }
82
- /**
83
- * Get the name of a room by ID
84
- */
85
- function getRoomName(world, roomId) {
86
- const room = world.getEntity(roomId);
87
- if (!room)
88
- return roomId;
89
- const identity = room.get?.('identity') || room.traits?.get?.('identity');
90
- return identity?.name || roomId;
91
- }
92
- /**
93
- * Check if an entity is "alive" (for NPCs/Combatants)
94
- */
95
- function isEntityAlive(entity) {
96
- // Check for CombatantTrait (used by troll, thief, etc.)
97
- const combatantTrait = entity.get?.('combatant') || entity.traits?.get?.('combatant');
98
- if (combatantTrait) {
99
- // CombatantTrait uses isAlive (not isDead)
100
- if (combatantTrait.isAlive === false)
101
- return false;
102
- // Check health
103
- if (combatantTrait.health !== undefined && combatantTrait.health <= 0)
104
- return false;
105
- }
106
- // Check for NPC trait with health/alive status
107
- const npcTrait = entity.get?.('npc') || entity.traits?.get?.('npc');
108
- if (npcTrait) {
109
- // Check isDead flag
110
- if (entity.isDead === true)
111
- return false;
112
- if (npcTrait.isDead === true)
113
- return false;
114
- if (npcTrait.isAlive === false)
115
- return false;
116
- // Check health
117
- if (npcTrait.health !== undefined && npcTrait.health <= 0)
118
- return false;
119
- }
120
- // Default to alive if no NPC/combatant trait or death indicators
121
- return true;
122
- }
123
- /**
124
- * Parse and evaluate a condition expression
125
- */
126
- export function evaluateCondition(condition, world, playerId) {
127
- const trimmed = condition.trim();
128
- // Handle negation prefix
129
- const isNegated = trimmed.toLowerCase().startsWith('not ');
130
- const expr = isNegated ? trimmed.slice(4).trim() : trimmed;
131
- // Try each pattern
132
- let result = tryLocationEquals(expr, world, playerId);
133
- if (result)
134
- return applyNegation(result, isNegated);
135
- result = tryRoomContains(expr, world, playerId);
136
- if (result)
137
- return applyNegation(result, isNegated);
138
- result = tryInventoryContains(expr, world, playerId);
139
- if (result)
140
- return applyNegation(result, isNegated);
141
- result = tryEntityExists(expr, world);
142
- if (result)
143
- return applyNegation(result, isNegated);
144
- result = tryEntityAlive(expr, world);
145
- if (result)
146
- return applyNegation(result, isNegated);
147
- result = tryEntityInRoom(expr, world);
148
- if (result)
149
- return applyNegation(result, isNegated);
150
- // Unknown condition format
151
- return {
152
- met: false,
153
- reason: `Unknown condition format: "${condition}"`
154
- };
155
- }
156
- /**
157
- * Apply negation to a result
158
- */
159
- function applyNegation(result, negate) {
160
- if (!negate)
161
- return result;
162
- return {
163
- met: !result.met,
164
- reason: `NOT (${result.reason})`
165
- };
166
- }
167
- /**
168
- * Pattern: location = "Room Name"
169
- */
170
- function tryLocationEquals(expr, world, playerId) {
171
- const match = expr.match(/^location\s*=\s*"([^"]+)"$/i);
172
- if (!match)
173
- return null;
174
- const targetRoomName = match[1];
175
- const currentRoomId = world.getLocation(playerId);
176
- if (!currentRoomId) {
177
- return { met: false, reason: `Player location unknown` };
178
- }
179
- const currentRoomName = getRoomName(world, currentRoomId);
180
- const met = currentRoomName.toLowerCase() === targetRoomName.toLowerCase() ||
181
- currentRoomName.toLowerCase().includes(targetRoomName.toLowerCase());
182
- return {
183
- met,
184
- reason: `Player is in "${currentRoomName}" (expected "${targetRoomName}")`
185
- };
186
- }
187
- /**
188
- * Pattern: room contains "entity"
189
- */
190
- function tryRoomContains(expr, world, playerId) {
191
- const match = expr.match(/^room\s+contains\s+"([^"]+)"$/i);
192
- if (!match)
193
- return null;
194
- const entityName = match[1];
195
- const currentRoomId = world.getLocation(playerId);
196
- if (!currentRoomId) {
197
- return { met: false, reason: `Player location unknown` };
198
- }
199
- // Get room contents
200
- const contents = world.getContents(currentRoomId);
201
- const entityNameLower = entityName.toLowerCase();
202
- const found = contents.some((item) => {
203
- const identity = item.get?.('identity') || item.traits?.get?.('identity');
204
- if (!identity)
205
- return false;
206
- const itemName = (identity.name || '').toLowerCase();
207
- const aliases = (identity.aliases || []).map((a) => a.toLowerCase());
208
- return itemName === entityNameLower ||
209
- itemName.includes(entityNameLower) ||
210
- aliases.some((a) => a === entityNameLower || a.includes(entityNameLower));
211
- });
212
- const roomName = getRoomName(world, currentRoomId);
213
- return {
214
- met: found,
215
- reason: found
216
- ? `"${entityName}" found in ${roomName}`
217
- : `"${entityName}" not found in ${roomName}`
218
- };
219
- }
220
- /**
221
- * Pattern: inventory contains "item"
222
- */
223
- function tryInventoryContains(expr, world, playerId) {
224
- const match = expr.match(/^inventory\s+contains\s+"([^"]+)"$/i);
225
- if (!match)
226
- return null;
227
- const itemName = match[1];
228
- // Get player inventory
229
- const inventory = world.getContents(playerId, { includeWorn: true });
230
- const itemNameLower = itemName.toLowerCase();
231
- const found = inventory.some((item) => {
232
- const identity = item.get?.('identity') || item.traits?.get?.('identity');
233
- if (!identity)
234
- return false;
235
- const name = (identity.name || '').toLowerCase();
236
- const aliases = (identity.aliases || []).map((a) => a.toLowerCase());
237
- return name === itemNameLower ||
238
- name.includes(itemNameLower) ||
239
- aliases.some((a) => a === itemNameLower || a.includes(itemNameLower));
240
- });
241
- return {
242
- met: found,
243
- reason: found
244
- ? `"${itemName}" found in inventory`
245
- : `"${itemName}" not in inventory`
246
- };
247
- }
248
- /**
249
- * Pattern: entity "X" exists
250
- */
251
- function tryEntityExists(expr, world) {
252
- const match = expr.match(/^entity\s+"([^"]+)"\s+exists$/i);
253
- if (!match)
254
- return null;
255
- const entityName = match[1];
256
- const entity = findEntityByName(world, entityName);
257
- return {
258
- met: entity !== null,
259
- reason: entity
260
- ? `Entity "${entityName}" exists`
261
- : `Entity "${entityName}" not found`
262
- };
263
- }
264
- /**
265
- * Pattern: entity "X" alive
266
- */
267
- function tryEntityAlive(expr, world) {
268
- const match = expr.match(/^entity\s+"([^"]+)"\s+alive$/i);
269
- if (!match)
270
- return null;
271
- const entityName = match[1];
272
- const entity = findEntityByName(world, entityName);
273
- if (!entity) {
274
- return { met: false, reason: `Entity "${entityName}" not found` };
275
- }
276
- const alive = isEntityAlive(entity);
277
- return {
278
- met: alive,
279
- reason: alive
280
- ? `Entity "${entityName}" is alive`
281
- : `Entity "${entityName}" is dead`
282
- };
283
- }
284
- /**
285
- * Pattern: entity "X" in "Room"
286
- */
287
- function tryEntityInRoom(expr, world) {
288
- const match = expr.match(/^entity\s+"([^"]+)"\s+in\s+"([^"]+)"$/i);
289
- if (!match)
290
- return null;
291
- const entityName = match[1];
292
- const roomName = match[2];
293
- const entity = findEntityByName(world, entityName);
294
- if (!entity) {
295
- return { met: false, reason: `Entity "${entityName}" not found` };
296
- }
297
- const targetRoom = findRoomByName(world, roomName);
298
- if (!targetRoom) {
299
- return { met: false, reason: `Room "${roomName}" not found` };
300
- }
301
- const entityLocation = world.getLocation(entity.id);
302
- const met = entityLocation === targetRoom.id;
303
- const actualRoomName = entityLocation ? getRoomName(world, entityLocation) : 'unknown';
304
- return {
305
- met,
306
- reason: met
307
- ? `"${entityName}" is in "${roomName}"`
308
- : `"${entityName}" is in "${actualRoomName}", not "${roomName}"`
309
- };
310
- }
311
- //# sourceMappingURL=condition-evaluator.js.map