@sharpee/engine 0.9.60-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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +328 -0
  3. package/dist/action-context-factory.d.ts +11 -0
  4. package/dist/action-context-factory.d.ts.map +1 -0
  5. package/dist/action-context-factory.js +258 -0
  6. package/dist/action-context-factory.js.map +1 -0
  7. package/dist/capability-dispatch-helper.d.ts +106 -0
  8. package/dist/capability-dispatch-helper.d.ts.map +1 -0
  9. package/dist/capability-dispatch-helper.js +269 -0
  10. package/dist/capability-dispatch-helper.js.map +1 -0
  11. package/dist/command-executor.d.ts +53 -0
  12. package/dist/command-executor.d.ts.map +1 -0
  13. package/dist/command-executor.js +329 -0
  14. package/dist/command-executor.js.map +1 -0
  15. package/dist/event-adapter.d.ts +44 -0
  16. package/dist/event-adapter.d.ts.map +1 -0
  17. package/dist/event-adapter.js +127 -0
  18. package/dist/event-adapter.js.map +1 -0
  19. package/dist/event-sequencer.d.ts +73 -0
  20. package/dist/event-sequencer.d.ts.map +1 -0
  21. package/dist/event-sequencer.js +134 -0
  22. package/dist/event-sequencer.js.map +1 -0
  23. package/dist/events/event-emitter.d.ts +34 -0
  24. package/dist/events/event-emitter.d.ts.map +1 -0
  25. package/dist/events/event-emitter.js +67 -0
  26. package/dist/events/event-emitter.js.map +1 -0
  27. package/dist/game-engine.d.ts +292 -0
  28. package/dist/game-engine.d.ts.map +1 -0
  29. package/dist/game-engine.js +1631 -0
  30. package/dist/game-engine.js.map +1 -0
  31. package/dist/index.d.ts +27 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +62 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/narrative/index.d.ts +5 -0
  36. package/dist/narrative/index.d.ts.map +1 -0
  37. package/dist/narrative/index.js +10 -0
  38. package/dist/narrative/index.js.map +1 -0
  39. package/dist/narrative/narrative-settings.d.ts +73 -0
  40. package/dist/narrative/narrative-settings.d.ts.map +1 -0
  41. package/dist/narrative/narrative-settings.js +28 -0
  42. package/dist/narrative/narrative-settings.js.map +1 -0
  43. package/dist/parser-interface.d.ts +77 -0
  44. package/dist/parser-interface.d.ts.map +1 -0
  45. package/dist/parser-interface.js +48 -0
  46. package/dist/parser-interface.js.map +1 -0
  47. package/dist/platform-operations.d.ts +83 -0
  48. package/dist/platform-operations.d.ts.map +1 -0
  49. package/dist/platform-operations.js +218 -0
  50. package/dist/platform-operations.js.map +1 -0
  51. package/dist/save-restore-service.d.ts +133 -0
  52. package/dist/save-restore-service.d.ts.map +1 -0
  53. package/dist/save-restore-service.js +446 -0
  54. package/dist/save-restore-service.js.map +1 -0
  55. package/dist/scheduler/index.d.ts +9 -0
  56. package/dist/scheduler/index.d.ts.map +1 -0
  57. package/dist/scheduler/index.js +25 -0
  58. package/dist/scheduler/index.js.map +1 -0
  59. package/dist/scheduler/scheduler-service.d.ts +75 -0
  60. package/dist/scheduler/scheduler-service.d.ts.map +1 -0
  61. package/dist/scheduler/scheduler-service.js +310 -0
  62. package/dist/scheduler/scheduler-service.js.map +1 -0
  63. package/dist/scheduler/seeded-random.d.ts +7 -0
  64. package/dist/scheduler/seeded-random.d.ts.map +1 -0
  65. package/dist/scheduler/seeded-random.js +11 -0
  66. package/dist/scheduler/seeded-random.js.map +1 -0
  67. package/dist/scheduler/types.d.ts +134 -0
  68. package/dist/scheduler/types.d.ts.map +1 -0
  69. package/dist/scheduler/types.js +9 -0
  70. package/dist/scheduler/types.js.map +1 -0
  71. package/dist/shared-data-keys.d.ts +53 -0
  72. package/dist/shared-data-keys.d.ts.map +1 -0
  73. package/dist/shared-data-keys.js +29 -0
  74. package/dist/shared-data-keys.js.map +1 -0
  75. package/dist/story.d.ts +211 -0
  76. package/dist/story.d.ts.map +1 -0
  77. package/dist/story.js +60 -0
  78. package/dist/story.js.map +1 -0
  79. package/dist/test-helpers/mock-text-service.d.ts +11 -0
  80. package/dist/test-helpers/mock-text-service.d.ts.map +1 -0
  81. package/dist/test-helpers/mock-text-service.js +47 -0
  82. package/dist/test-helpers/mock-text-service.js.map +1 -0
  83. package/dist/turn-event-processor.d.ts +89 -0
  84. package/dist/turn-event-processor.d.ts.map +1 -0
  85. package/dist/turn-event-processor.js +144 -0
  86. package/dist/turn-event-processor.js.map +1 -0
  87. package/dist/types.d.ts +214 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +8 -0
  90. package/dist/types.js.map +1 -0
  91. package/dist/vocabulary-manager.d.ts +35 -0
  92. package/dist/vocabulary-manager.d.ts.map +1 -0
  93. package/dist/vocabulary-manager.js +74 -0
  94. package/dist/vocabulary-manager.js.map +1 -0
  95. package/package.json +70 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 David Cornelson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,328 @@
1
+ # @sharpee/engine
2
+
3
+ Runtime engine for the Sharpee IF Platform. This package provides the core game loop, command execution, and turn management.
4
+
5
+ > **Architecture Update (Phase 3.5)**: The CommandExecutor has been refactored from a 723-line god object to a 177-line thin orchestrator. Actions now own their complete event lifecycle through the three-phase pattern (validate/execute/report).
6
+
7
+ ## Overview
8
+
9
+ The engine package brings together all the Sharpee components into a running game:
10
+
11
+ - **GameEngine**: Main runtime that manages game state and turn execution
12
+ - **CommandExecutor**: Thin orchestrator (177 lines) that coordinates the action pipeline
13
+ - **EventSequencer**: Ensures events are properly ordered within turns (1.1, 1.2, 1.3...)
14
+
15
+ ## Architecture
16
+
17
+ ```
18
+ User Input
19
+
20
+ [GameEngine]
21
+
22
+ [CommandExecutor] (Thin Orchestrator)
23
+ ├─→ [Parser] → ParsedCommand
24
+ ├─→ [Validator] → ValidatedCommand
25
+ └─→ [Action] (Three-Phase Pattern)
26
+ ├─→ validate() → ValidationResult
27
+ ├─→ execute() → Mutations only
28
+ └─→ report() → ISemanticEvent[]
29
+
30
+ [EventProcessor] → World Changes
31
+
32
+ Turn Result
33
+ ```
34
+
35
+ ### Action Three-Phase Pattern
36
+
37
+ Actions follow a strict three-phase pattern for clean separation of concerns:
38
+
39
+ 1. **Validate Phase**: Check if the action can be performed (no mutations)
40
+ 2. **Execute Phase**: Perform state mutations only (no events)
41
+ 3. **Report Phase**: Generate events based on final state (no mutations)
42
+
43
+ The CommandExecutor simply orchestrates these phases, delegating all responsibility to the appropriate components. Actions own their complete event lifecycle, including error events.
44
+
45
+ ## Basic Usage
46
+
47
+ ```typescript
48
+ import { createStandardEngine } from '@sharpee/engine';
49
+ import { WorldModel } from '@sharpee/world-model';
50
+
51
+ // Create a game engine
52
+ const engine = createStandardEngine();
53
+
54
+ // Set language (NEW: automatic parser and language provider loading)
55
+ await engine.setLanguage('en-US');
56
+
57
+ // Or use a story with language configuration
58
+ const story = {
59
+ config: {
60
+ id: 'my-story',
61
+ title: 'My Adventure',
62
+ author: 'Me',
63
+ version: '1.0.0',
64
+ language: 'en-US' // Language automatically loaded
65
+ },
66
+ initializeWorld: (world) => { /* ... */ },
67
+ createPlayer: (world) => { /* ... */ }
68
+ };
69
+
70
+ await engine.setStory(story); // Automatically sets up language
71
+
72
+ // Start the engine
73
+ engine.start();
74
+
75
+ // Execute turns
76
+ const result = await engine.executeTurn('take sword');
77
+ console.log(`Turn ${result.turn}: ${result.success ? 'Success' : 'Failed'}`);
78
+
79
+ // Access game state
80
+ const context = engine.getContext();
81
+ console.log(`Current turn: ${context.currentTurn}`);
82
+
83
+ // Access parser and language provider if needed
84
+ const parser = engine.getParser();
85
+ const languageProvider = engine.getLanguageProvider();
86
+ ```
87
+
88
+ ## Custom Game Engine
89
+
90
+ ```typescript
91
+ import { GameEngine, EngineConfig } from '@sharpee/engine';
92
+ import { IWorldModel, IFEntity } from '@sharpee/world-model';
93
+
94
+ // Create your world
95
+ const world: IWorldModel = createMyWorld();
96
+ const player: IFEntity = createPlayer();
97
+
98
+ // Configure engine
99
+ const config: EngineConfig = {
100
+ maxHistory: 50,
101
+ collectTiming: true,
102
+ onEvent: (event) => console.log(`Event: ${event.type}`),
103
+ onError: (error, context) => console.error(`Error at turn ${context.currentTurn}:`, error)
104
+ };
105
+
106
+ // Create engine
107
+ const engine = new GameEngine(world, player, config);
108
+
109
+ // Listen to engine events
110
+ engine.on('turn:complete', (result) => {
111
+ console.log(`Turn ${result.turn} complete with ${result.events.length} events`);
112
+ });
113
+
114
+ engine.on('game:over', (context) => {
115
+ console.log('Game over!');
116
+ });
117
+ ```
118
+
119
+ ## Atomic Events Architecture
120
+
121
+ Events are self-contained with all necessary data embedded at creation time:
122
+
123
+ ```typescript
124
+ // Example event from taking action
125
+ {
126
+ type: 'if.event.taken',
127
+ timestamp: 1692345678,
128
+ data: {
129
+ itemSnapshot: { // Complete entity state
130
+ id: 'sword',
131
+ name: 'silver sword',
132
+ description: 'A gleaming blade',
133
+ location: 'player',
134
+ traits: { /* ... */ }
135
+ },
136
+ actorSnapshot: { /* ... */ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ This enables:
142
+ - **Historical Replay**: Events contain complete state at that moment
143
+ - **No World Queries**: Text services use embedded data, not world lookups
144
+ - **Consistency**: Entity state is captured after all mutations complete
145
+
146
+ ## Event Sequencing
147
+
148
+ Events are automatically sequenced within turns:
149
+
150
+ ```typescript
151
+ // Turn 1
152
+ 1.1 - action.started
153
+ 1.2 - if.event.taken (main action)
154
+ 1.3 - action.success
155
+
156
+ // Turn 2
157
+ 2.1 - action.started
158
+ 2.2 - if.event.exited (leaving room)
159
+ 2.3 - if.event.entered (entering room)
160
+ 2.4 - if.event.looked (auto-look)
161
+ 2.5 - action.success
162
+ ```
163
+
164
+ ## Language Management
165
+
166
+ The engine automatically loads language providers and parsers based on language codes:
167
+
168
+ ```typescript
169
+ // Set language directly
170
+ await engine.setLanguage('en-US'); // Loads @sharpee/lang-en-us and @sharpee/parser-en-us
171
+
172
+ // Change language at runtime
173
+ await engine.setLanguage('es'); // Switches to Spanish
174
+
175
+ // Language from story config
176
+ const story = {
177
+ config: { language: 'ja', /* ... */ }
178
+ };
179
+ await engine.setStory(story); // Automatically uses Japanese
180
+ ```
181
+
182
+ ### Naming Convention
183
+
184
+ Language packages follow a predictable naming pattern:
185
+ - Language Provider: `@sharpee/lang-{language-code}`
186
+ - Parser: `@sharpee/parser-{language-code}`
187
+
188
+ For example:
189
+ - English (US): `@sharpee/lang-en-us`, `@sharpee/parser-en-us`
190
+ - Spanish: `@sharpee/lang-es`, `@sharpee/parser-es`
191
+ - Japanese: `@sharpee/lang-ja`, `@sharpee/parser-ja`
192
+
193
+ ## Save/Load
194
+
195
+ ```typescript
196
+ // Save game state
197
+ const saveData = engine.saveState();
198
+ localStorage.setItem('save', JSON.stringify(saveData));
199
+
200
+ // Load game state
201
+ const loadData = JSON.parse(localStorage.getItem('save'));
202
+ engine.loadState(loadData);
203
+ ```
204
+
205
+ ## Integration with Story Files
206
+
207
+ The engine is designed to work with TypeScript story files:
208
+
209
+ ```typescript
210
+ // my-story.ts
211
+ import { Story } from '@sharpee/forge';
212
+
213
+ export default new Story()
214
+ .title('My Adventure')
215
+ .author('Me')
216
+ .room('start', room => room
217
+ .name('Starting Room')
218
+ .description('You are in a small room.')
219
+ .exit('north', 'hallway')
220
+ )
221
+ .build();
222
+ ```
223
+
224
+ ## API Reference
225
+
226
+ ### GameEngine
227
+
228
+ - `start()`: Start the engine
229
+ - `stop()`: Stop the engine
230
+ - `executeTurn(input: string)`: Execute a turn with user input
231
+ - `getContext()`: Get current game context
232
+ - `getWorld()`: Get world model
233
+ - `saveState()`: Save game state
234
+ - `loadState(state)`: Load game state
235
+ - `getHistory()`: Get turn history
236
+ - `getRecentEvents(count)`: Get recent events
237
+ - `setLanguage(languageCode: string)`: Set language (automatically loads parser and language provider)
238
+ - `setStory(story: Story)`: Set story (automatically configures language from story config)
239
+ - `getParser()`: Get current parser instance
240
+ - `getLanguageProvider()`: Get current language provider instance
241
+
242
+ ### Events
243
+
244
+ The engine emits these events:
245
+
246
+ - `turn:start`: Turn is starting
247
+ - `turn:complete`: Turn completed successfully
248
+ - `turn:failed`: Turn failed with error
249
+ - `event`: Individual event processed
250
+ - `state:changed`: Game state changed
251
+ - `game:over`: Game has ended
252
+
253
+ ### Turn Results
254
+
255
+ Each turn returns:
256
+
257
+ ```typescript
258
+ interface TurnResult {
259
+ turn: number;
260
+ input: string;
261
+ events: SequencedEvent[];
262
+ success: boolean;
263
+ error?: string;
264
+ actionId?: string;
265
+ parsedCommand?: IParsedCommand;
266
+ timing?: TimingData;
267
+ }
268
+ ```
269
+
270
+ Where SequencedEvent includes:
271
+ ```typescript
272
+ interface SequencedEvent {
273
+ type: string;
274
+ data: any;
275
+ sequence: number;
276
+ timestamp: Date;
277
+ turn: number;
278
+ scope: 'turn' | 'global' | 'system';
279
+ source?: string;
280
+ }
281
+ ```
282
+
283
+ ## Development
284
+
285
+ ```bash
286
+ # Build the package
287
+ pnpm build
288
+
289
+ # Run tests
290
+ pnpm test
291
+
292
+ # Run tests with coverage
293
+ pnpm test:coverage
294
+
295
+ # Watch mode for tests
296
+ pnpm test:watch
297
+ ```
298
+
299
+ ## Testing
300
+
301
+ The engine package includes comprehensive test coverage:
302
+
303
+ ### Unit Tests
304
+ - `game-engine.test.ts` - Core game engine functionality
305
+ - `command-executor.test.ts` - Command parsing and execution
306
+ - `event-sequencer.test.ts` - Event ordering and utilities
307
+ - `story.test.ts` - Story interface and configuration
308
+ - `text-service.test.ts` - Text output formatting
309
+ - `types.test.ts` - Type definitions and contracts
310
+
311
+ ### Integration Tests
312
+ - `integration.test.ts` - Full game flow and component interaction
313
+
314
+ ### Test Fixtures
315
+ - `fixtures/index.ts` - Reusable test utilities and mocks
316
+
317
+ ### Running Tests
318
+
319
+ ```bash
320
+ # Run all tests
321
+ pnpm test
322
+
323
+ # Run specific test file
324
+ pnpm test game-engine
325
+
326
+ # Generate coverage report
327
+ pnpm test:coverage
328
+ ```
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Action Context Factory - Creates ActionContext for action execution
3
+ */
4
+ import { ActionContext, Action, ScopeResolver, ValidatedCommand } from '@sharpee/stdlib';
5
+ import { WorldModel } from '@sharpee/world-model';
6
+ import { GameContext } from './types';
7
+ /**
8
+ * Create an ActionContext for action execution
9
+ */
10
+ export declare function createActionContext(world: WorldModel, gameContext: GameContext, command: ValidatedCommand, action: Action, scopeResolver: ScopeResolver): ActionContext;
11
+ //# sourceMappingURL=action-context-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-context-factory.d.ts","sourceRoot":"","sources":["../src/action-context-factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAA+E,MAAM,iBAAiB,CAAC;AACtK,OAAO,EAAE,UAAU,EAAuB,MAAM,sBAAsB,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AA+CtC;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,GAC3B,aAAa,CAuPf"}
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ /**
3
+ * Action Context Factory - Creates ActionContext for action execution
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createActionContext = createActionContext;
7
+ const stdlib_1 = require("@sharpee/stdlib");
8
+ const world_model_1 = require("@sharpee/world-model");
9
+ const core_1 = require("@sharpee/core");
10
+ const shared_data_keys_1 = require("./shared-data-keys");
11
+ /**
12
+ * Helper to get entity from command slot
13
+ */
14
+ function getEntityFromSlot(command, slot) {
15
+ switch (slot) {
16
+ case 'target':
17
+ case 'directObject':
18
+ case 'item':
19
+ return command.directObject?.entity ?? null;
20
+ case 'container':
21
+ case 'recipient':
22
+ case 'instrument':
23
+ case 'indirectObject':
24
+ return command.indirectObject?.entity ?? null;
25
+ default:
26
+ return command.directObject?.entity ?? null;
27
+ }
28
+ }
29
+ /**
30
+ * Generate appropriate scope error based on requirement and actual scope
31
+ */
32
+ function getScopeError(required, actual, entity) {
33
+ const params = { item: entity.name };
34
+ if (actual === stdlib_1.ScopeLevel.UNAWARE) {
35
+ return { valid: false, error: stdlib_1.ScopeErrors.NOT_KNOWN, params };
36
+ }
37
+ if (required >= stdlib_1.ScopeLevel.VISIBLE && actual < stdlib_1.ScopeLevel.VISIBLE) {
38
+ return { valid: false, error: stdlib_1.ScopeErrors.NOT_VISIBLE, params };
39
+ }
40
+ if (required >= stdlib_1.ScopeLevel.REACHABLE && actual < stdlib_1.ScopeLevel.REACHABLE) {
41
+ return { valid: false, error: stdlib_1.ScopeErrors.NOT_REACHABLE, params };
42
+ }
43
+ if (required >= stdlib_1.ScopeLevel.CARRIED && actual < stdlib_1.ScopeLevel.CARRIED) {
44
+ return { valid: false, error: stdlib_1.ScopeErrors.NOT_CARRIED, params };
45
+ }
46
+ return { valid: false, error: stdlib_1.ScopeErrors.OUT_OF_SCOPE, params };
47
+ }
48
+ /**
49
+ * Create an ActionContext for action execution
50
+ */
51
+ function createActionContext(world, gameContext, command, action, scopeResolver) {
52
+ const player = gameContext.player;
53
+ const currentLocation = world.getLocation(player.id)
54
+ ? world.getEntity(world.getLocation(player.id))
55
+ : player;
56
+ // Create sharedData object separately so it can be referenced in closures
57
+ const sharedData = {};
58
+ // Create the event method
59
+ const event = (type, data) => {
60
+ // Add standard entities
61
+ const entities = {
62
+ actor: player.id,
63
+ location: currentLocation?.id || player.id
64
+ };
65
+ // Add entities from command
66
+ if (command.directObject?.entity) {
67
+ entities.target = command.directObject.entity.id;
68
+ }
69
+ if (command.indirectObject?.entity) {
70
+ entities.indirect = command.indirectObject.entity.id;
71
+ }
72
+ // Create the event
73
+ return {
74
+ id: `evt_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
75
+ type,
76
+ timestamp: Date.now(),
77
+ data: {
78
+ ...data,
79
+ // Include action context in data instead of metadata
80
+ actionId: action.id,
81
+ turn: gameContext.currentTurn
82
+ },
83
+ entities
84
+ };
85
+ };
86
+ return {
87
+ // World querying
88
+ world,
89
+ player,
90
+ currentLocation: currentLocation,
91
+ command,
92
+ scopeResolver,
93
+ action,
94
+ // Shared data for passing information between phases
95
+ sharedData,
96
+ // Validation result - set by CommandExecutor after validate() phase
97
+ validationResult: undefined,
98
+ // Scope checking methods (delegate to scopeResolver)
99
+ canSee: (entity) => {
100
+ return scopeResolver.canSee(player, entity);
101
+ },
102
+ canReach: (entity) => {
103
+ return scopeResolver.canReach(player, entity);
104
+ },
105
+ canTake: (entity) => {
106
+ // Basic implementation - can be enhanced
107
+ return !entity.has('if.trait.scenery') &&
108
+ !entity.has('if.trait.fixed') &&
109
+ entity.type !== 'room' &&
110
+ entity.type !== 'location';
111
+ },
112
+ isInScope: (entity) => {
113
+ const level = scopeResolver.getScope(player, entity);
114
+ return level >= stdlib_1.ScopeLevel.AWARE;
115
+ },
116
+ getVisible: () => {
117
+ return scopeResolver.getVisible(player);
118
+ },
119
+ getInScope: () => {
120
+ // Get all entities and filter by scope
121
+ const allEntities = world.getAllEntities();
122
+ return allEntities.filter(entity => {
123
+ const level = scopeResolver.getScope(player, entity);
124
+ return level >= stdlib_1.ScopeLevel.AWARE;
125
+ });
126
+ },
127
+ // Scope validation methods (Phase 4 parser refactor)
128
+ getEntityScope: (entity) => {
129
+ return scopeResolver.getScope(player, entity);
130
+ },
131
+ getSlotScope: (slot) => {
132
+ const entity = getEntityFromSlot(command, slot);
133
+ if (!entity) {
134
+ return stdlib_1.ScopeLevel.UNAWARE;
135
+ }
136
+ return scopeResolver.getScope(player, entity);
137
+ },
138
+ requireScope: (entity, required) => {
139
+ const actualScope = scopeResolver.getScope(player, entity);
140
+ if (actualScope >= required) {
141
+ return { ok: true, actualScope };
142
+ }
143
+ const error = getScopeError(required, actualScope, entity);
144
+ return { ok: false, error, actualScope };
145
+ },
146
+ requireSlotScope: (slot, required) => {
147
+ const entity = getEntityFromSlot(command, slot);
148
+ if (!entity) {
149
+ return {
150
+ ok: false,
151
+ error: { valid: false, error: 'no_target', params: { slot } }
152
+ };
153
+ }
154
+ const actualScope = scopeResolver.getScope(player, entity);
155
+ if (actualScope >= required) {
156
+ return { ok: true, actualScope };
157
+ }
158
+ const error = getScopeError(required, actualScope, entity);
159
+ return { ok: false, error, actualScope };
160
+ },
161
+ requireCarriedOrImplicitTake: (entity) => {
162
+ const actualScope = scopeResolver.getScope(player, entity);
163
+ // Case 1: Already carried - success, no implicit take needed
164
+ if (actualScope >= stdlib_1.ScopeLevel.CARRIED) {
165
+ return { ok: true };
166
+ }
167
+ // Case 2: Not reachable - can't take it, return scope error
168
+ if (actualScope < stdlib_1.ScopeLevel.REACHABLE) {
169
+ const error = getScopeError(stdlib_1.ScopeLevel.REACHABLE, actualScope, entity);
170
+ return { ok: false, error };
171
+ }
172
+ // Case 3: Reachable but not carried - attempt implicit take
173
+ // Check if implicit take is disabled at story level (ADR-104)
174
+ if (gameContext.implicitActions?.implicitTake === false) {
175
+ return {
176
+ ok: false,
177
+ error: { valid: false, error: stdlib_1.ScopeErrors.NOT_CARRIED, params: { item: entity.name } }
178
+ };
179
+ }
180
+ // Check if implicit take is disabled at action level (ADR-104)
181
+ if (action.allowImplicitTake === false) {
182
+ return {
183
+ ok: false,
184
+ error: { valid: false, error: stdlib_1.ScopeErrors.NOT_CARRIED, params: { item: entity.name } }
185
+ };
186
+ }
187
+ // Check if entity can be taken (not scenery, room, door)
188
+ if (entity.has(world_model_1.TraitType.SCENERY) || entity.has(world_model_1.TraitType.ROOM) || entity.has(world_model_1.TraitType.DOOR)) {
189
+ return {
190
+ ok: false,
191
+ error: { valid: false, error: 'fixed_in_place', params: { item: entity.name } }
192
+ };
193
+ }
194
+ // Create a synthetic command for the taking action
195
+ const takeCommand = {
196
+ parsed: {
197
+ rawInput: `take ${entity.name}`,
198
+ action: stdlib_1.takingAction.id,
199
+ tokens: [],
200
+ structure: { verb: { tokens: [0], text: 'take', head: 'take' } },
201
+ pattern: 'VERB_NOUN',
202
+ confidence: 1.0
203
+ },
204
+ actionId: stdlib_1.takingAction.id,
205
+ directObject: {
206
+ entity,
207
+ parsed: {
208
+ text: entity.name,
209
+ candidates: [entity.name]
210
+ }
211
+ }
212
+ };
213
+ // Create a sub-context for the taking action
214
+ const takeContext = createActionContext(world, gameContext, takeCommand, stdlib_1.takingAction, scopeResolver);
215
+ // Run the taking action's validate phase
216
+ const validation = stdlib_1.takingAction.validate(takeContext);
217
+ if (!validation.valid) {
218
+ // Take validation failed - return the error
219
+ return {
220
+ ok: false,
221
+ error: {
222
+ valid: false,
223
+ error: validation.error || 'cannot_take',
224
+ params: validation.params
225
+ }
226
+ };
227
+ }
228
+ // Execute the taking action
229
+ stdlib_1.takingAction.execute(takeContext);
230
+ // Get the report events from the taking action
231
+ const takeEvents = stdlib_1.takingAction.report ? stdlib_1.takingAction.report(takeContext) : [];
232
+ // Filter out action.success events - the implicit_take message replaces them
233
+ // Keep if.event.taken for state tracking
234
+ const filteredTakeEvents = takeEvents.filter(e => e.type !== 'action.success');
235
+ // Create the implicit take event (for "(first taking the X)" message)
236
+ const implicitTakeEvent = (0, core_1.createEvent)('if.event.implicit_take', {
237
+ item: entity.id,
238
+ itemName: entity.name
239
+ }, {
240
+ actor: player.id,
241
+ target: entity.id,
242
+ location: currentLocation?.id || player.id
243
+ });
244
+ // Combine: implicit take notification + state change events (no success message)
245
+ const implicitTakeEvents = [implicitTakeEvent, ...filteredTakeEvents];
246
+ // Store in sharedData for the report phase to access
247
+ const existingEvents = sharedData[shared_data_keys_1.SharedDataKeys.IMPLICIT_TAKE_EVENTS] ?? [];
248
+ sharedData[shared_data_keys_1.SharedDataKeys.IMPLICIT_TAKE_EVENTS] = [...existingEvents, ...implicitTakeEvents];
249
+ return {
250
+ ok: true,
251
+ implicitTakeEvents
252
+ };
253
+ },
254
+ // Event creation
255
+ event
256
+ };
257
+ }
258
+ //# sourceMappingURL=action-context-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-context-factory.js","sourceRoot":"","sources":["../src/action-context-factory.ts"],"names":[],"mappings":"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"}