@ai-rpg-engine/modules 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/belief-provenance.d.ts +41 -0
  2. package/dist/belief-provenance.d.ts.map +1 -0
  3. package/dist/belief-provenance.js +254 -0
  4. package/dist/belief-provenance.js.map +1 -0
  5. package/dist/belief-provenance.test.d.ts +2 -0
  6. package/dist/belief-provenance.test.d.ts.map +1 -0
  7. package/dist/belief-provenance.test.js +139 -0
  8. package/dist/belief-provenance.test.js.map +1 -0
  9. package/dist/cognition-core.d.ts +89 -0
  10. package/dist/cognition-core.d.ts.map +1 -0
  11. package/dist/cognition-core.js +370 -0
  12. package/dist/cognition-core.js.map +1 -0
  13. package/dist/cognition-core.test.d.ts +2 -0
  14. package/dist/cognition-core.test.d.ts.map +1 -0
  15. package/dist/cognition-core.test.js +215 -0
  16. package/dist/cognition-core.test.js.map +1 -0
  17. package/dist/combat-core.d.ts +11 -0
  18. package/dist/combat-core.d.ts.map +1 -0
  19. package/dist/combat-core.js +152 -0
  20. package/dist/combat-core.js.map +1 -0
  21. package/dist/dialogue-core.d.ts +10 -0
  22. package/dist/dialogue-core.d.ts.map +1 -0
  23. package/dist/dialogue-core.js +172 -0
  24. package/dist/dialogue-core.js.map +1 -0
  25. package/dist/district-core.d.ts +59 -0
  26. package/dist/district-core.d.ts.map +1 -0
  27. package/dist/district-core.js +224 -0
  28. package/dist/district-core.js.map +1 -0
  29. package/dist/district-core.test.d.ts +2 -0
  30. package/dist/district-core.test.d.ts.map +1 -0
  31. package/dist/district-core.test.js +157 -0
  32. package/dist/district-core.test.js.map +1 -0
  33. package/dist/environment-core.d.ts +78 -0
  34. package/dist/environment-core.d.ts.map +1 -0
  35. package/dist/environment-core.js +229 -0
  36. package/dist/environment-core.js.map +1 -0
  37. package/dist/environment-core.test.d.ts +2 -0
  38. package/dist/environment-core.test.d.ts.map +1 -0
  39. package/dist/environment-core.test.js +252 -0
  40. package/dist/environment-core.test.js.map +1 -0
  41. package/dist/faction-cognition.d.ts +39 -0
  42. package/dist/faction-cognition.d.ts.map +1 -0
  43. package/dist/faction-cognition.js +139 -0
  44. package/dist/faction-cognition.js.map +1 -0
  45. package/dist/faction-cognition.test.d.ts +2 -0
  46. package/dist/faction-cognition.test.d.ts.map +1 -0
  47. package/dist/faction-cognition.test.js +166 -0
  48. package/dist/faction-cognition.test.js.map +1 -0
  49. package/dist/index.d.ts +31 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +18 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/inventory-core.d.ts +10 -0
  54. package/dist/inventory-core.d.ts.map +1 -0
  55. package/dist/inventory-core.js +69 -0
  56. package/dist/inventory-core.js.map +1 -0
  57. package/dist/knowledge-decay.test.d.ts +2 -0
  58. package/dist/knowledge-decay.test.d.ts.map +1 -0
  59. package/dist/knowledge-decay.test.js +143 -0
  60. package/dist/knowledge-decay.test.js.map +1 -0
  61. package/dist/narrative-authority.d.ts +40 -0
  62. package/dist/narrative-authority.d.ts.map +1 -0
  63. package/dist/narrative-authority.js +89 -0
  64. package/dist/narrative-authority.js.map +1 -0
  65. package/dist/narrative-authority.test.d.ts +2 -0
  66. package/dist/narrative-authority.test.d.ts.map +1 -0
  67. package/dist/narrative-authority.test.js +237 -0
  68. package/dist/narrative-authority.test.js.map +1 -0
  69. package/dist/observer-presentation.d.ts +74 -0
  70. package/dist/observer-presentation.d.ts.map +1 -0
  71. package/dist/observer-presentation.js +277 -0
  72. package/dist/observer-presentation.js.map +1 -0
  73. package/dist/observer-presentation.test.d.ts +2 -0
  74. package/dist/observer-presentation.test.d.ts.map +1 -0
  75. package/dist/observer-presentation.test.js +156 -0
  76. package/dist/observer-presentation.test.js.map +1 -0
  77. package/dist/perception-filter.d.ts +46 -0
  78. package/dist/perception-filter.d.ts.map +1 -0
  79. package/dist/perception-filter.js +281 -0
  80. package/dist/perception-filter.js.map +1 -0
  81. package/dist/perception-filter.test.d.ts +2 -0
  82. package/dist/perception-filter.test.d.ts.map +1 -0
  83. package/dist/perception-filter.test.js +308 -0
  84. package/dist/perception-filter.test.js.map +1 -0
  85. package/dist/progression-core.d.ts +63 -0
  86. package/dist/progression-core.d.ts.map +1 -0
  87. package/dist/progression-core.js +232 -0
  88. package/dist/progression-core.js.map +1 -0
  89. package/dist/progression-core.test.d.ts +2 -0
  90. package/dist/progression-core.test.d.ts.map +1 -0
  91. package/dist/progression-core.test.js +328 -0
  92. package/dist/progression-core.test.js.map +1 -0
  93. package/dist/rumor-propagation.d.ts +31 -0
  94. package/dist/rumor-propagation.d.ts.map +1 -0
  95. package/dist/rumor-propagation.js +180 -0
  96. package/dist/rumor-propagation.js.map +1 -0
  97. package/dist/rumor-propagation.test.d.ts +2 -0
  98. package/dist/rumor-propagation.test.d.ts.map +1 -0
  99. package/dist/rumor-propagation.test.js +176 -0
  100. package/dist/rumor-propagation.test.js.map +1 -0
  101. package/dist/simulation-inspector.d.ts +78 -0
  102. package/dist/simulation-inspector.d.ts.map +1 -0
  103. package/dist/simulation-inspector.js +263 -0
  104. package/dist/simulation-inspector.js.map +1 -0
  105. package/dist/simulation-inspector.test.d.ts +2 -0
  106. package/dist/simulation-inspector.test.d.ts.map +1 -0
  107. package/dist/simulation-inspector.test.js +152 -0
  108. package/dist/simulation-inspector.test.js.map +1 -0
  109. package/dist/status-core.d.ts +17 -0
  110. package/dist/status-core.d.ts.map +1 -0
  111. package/dist/status-core.js +106 -0
  112. package/dist/status-core.js.map +1 -0
  113. package/dist/traversal-core.d.ts +3 -0
  114. package/dist/traversal-core.d.ts.map +1 -0
  115. package/dist/traversal-core.js +93 -0
  116. package/dist/traversal-core.js.map +1 -0
  117. package/package.json +34 -0
@@ -0,0 +1,308 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { createTestEngine } from '@ai-rpg-engine/core';
3
+ import { createCognitionCore, getCognition, setBelief, believes, getMemories, } from './cognition-core.js';
4
+ import { createPerceptionFilter, getPerceptionLog, didPerceive, whoPerceived, } from './perception-filter.js';
5
+ import { traversalCore } from './traversal-core.js';
6
+ import { combatCore } from './combat-core.js';
7
+ // Helper: AI entity with configurable perception stat
8
+ const makeAI = (id, name, zoneId, instinct = 5, overrides) => ({
9
+ id,
10
+ blueprintId: id,
11
+ type: 'enemy',
12
+ name,
13
+ tags: ['enemy'],
14
+ stats: { vigor: 5, instinct },
15
+ resources: { hp: 20, stamina: 5 },
16
+ statuses: [],
17
+ zoneId,
18
+ ai: { profileId: 'aggressive', goals: ['guard'], fears: [], alertLevel: 0, knowledge: {} },
19
+ ...overrides,
20
+ });
21
+ const makePlayer = (zoneId, overrides) => ({
22
+ id: 'player',
23
+ blueprintId: 'player',
24
+ type: 'player',
25
+ name: 'Hero',
26
+ tags: ['player'],
27
+ stats: { vigor: 5, instinct: 5 },
28
+ resources: { hp: 20, stamina: 5 },
29
+ statuses: [],
30
+ zoneId,
31
+ ...overrides,
32
+ });
33
+ describe('Perception filter — bright zone detection', () => {
34
+ it('guard with high perception detects player entering bright zone', () => {
35
+ const engine = createTestEngine({
36
+ modules: [traversalCore, createCognitionCore(), createPerceptionFilter()],
37
+ entities: [
38
+ makePlayer('a'),
39
+ makeAI('guard', 'Guard', 'b', 10), // High perception
40
+ ],
41
+ zones: [
42
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
43
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 10 },
44
+ ],
45
+ });
46
+ engine.submitAction('move', { targetIds: ['b'] });
47
+ const cog = getCognition(engine.world, 'guard');
48
+ // High perception + bright zone = detected
49
+ expect(believes(cog, 'player', 'present', true)).toBe(true);
50
+ expect(getMemories(cog, 'saw-entity').length).toBeGreaterThan(0);
51
+ });
52
+ it('guard with low perception in dark zone fails to detect hidden intruder', () => {
53
+ const engine = createTestEngine({
54
+ modules: [traversalCore, createCognitionCore(), createPerceptionFilter()],
55
+ entities: [
56
+ makePlayer('a', { visibility: { hidden: true } }),
57
+ makeAI('guard', 'Guard', 'b', 1), // Very low perception
58
+ ],
59
+ zones: [
60
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
61
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 0 }, // Pitch dark
62
+ ],
63
+ });
64
+ engine.submitAction('move', { targetIds: ['b'] });
65
+ const cog = getCognition(engine.world, 'guard');
66
+ // Low perception + dark + hidden = guaranteed failure
67
+ // instinct=1 → score = 7 + roll(1-50) = 8-57
68
+ // threshold = 30 + 10 (dark) + 20 (hidden) = 60
69
+ // max score 57 < 60 → always fails
70
+ expect(believes(cog, 'player', 'present', true)).toBe(false);
71
+ expect(getMemories(cog, 'saw-entity')).toHaveLength(0);
72
+ });
73
+ });
74
+ describe('Perception filter — perception log', () => {
75
+ it('logs perception attempts for each entity', () => {
76
+ const engine = createTestEngine({
77
+ modules: [traversalCore, createCognitionCore(), createPerceptionFilter()],
78
+ entities: [
79
+ makePlayer('a'),
80
+ makeAI('guard1', 'Guard 1', 'b', 10),
81
+ makeAI('guard2', 'Guard 2', 'b', 10),
82
+ ],
83
+ zones: [
84
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
85
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 10 },
86
+ ],
87
+ });
88
+ engine.submitAction('move', { targetIds: ['b'] });
89
+ // Both guards should have perception log entries
90
+ const log1 = getPerceptionLog(engine.world, 'guard1');
91
+ const log2 = getPerceptionLog(engine.world, 'guard2');
92
+ expect(log1.length).toBeGreaterThan(0);
93
+ expect(log2.length).toBeGreaterThan(0);
94
+ expect(log1[0].sense).toBe('sight');
95
+ expect(log2[0].sense).toBe('sight');
96
+ });
97
+ it('didPerceive returns entry for specific event', () => {
98
+ const engine = createTestEngine({
99
+ modules: [traversalCore, createCognitionCore(), createPerceptionFilter()],
100
+ entities: [
101
+ makePlayer('a'),
102
+ makeAI('guard', 'Guard', 'b', 10),
103
+ ],
104
+ zones: [
105
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
106
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 10 },
107
+ ],
108
+ });
109
+ const events = engine.submitAction('move', { targetIds: ['b'] });
110
+ const moveEvent = events.find((e) => e.type === 'world.zone.entered');
111
+ expect(moveEvent).toBeDefined();
112
+ const perceived = didPerceive(engine.world, 'guard', moveEvent.id);
113
+ expect(perceived).toBeDefined();
114
+ expect(perceived.detected).toBe(true);
115
+ });
116
+ it('whoPerceived returns all entities that perceived an event', () => {
117
+ const engine = createTestEngine({
118
+ modules: [traversalCore, createCognitionCore(), createPerceptionFilter()],
119
+ entities: [
120
+ makePlayer('a'),
121
+ makeAI('guard1', 'Guard 1', 'b', 10),
122
+ makeAI('guard2', 'Guard 2', 'b', 10),
123
+ ],
124
+ zones: [
125
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
126
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 10 },
127
+ ],
128
+ });
129
+ const events = engine.submitAction('move', { targetIds: ['b'] });
130
+ const moveEvent = events.find((e) => e.type === 'world.zone.entered');
131
+ const perceivers = whoPerceived(engine.world, moveEvent.id);
132
+ expect(perceivers.length).toBe(2);
133
+ });
134
+ });
135
+ describe('Perception filter — combat awareness', () => {
136
+ it('direct attack target always knows attacker (no perception needed)', () => {
137
+ const engine = createTestEngine({
138
+ modules: [traversalCore, combatCore, createCognitionCore(), createPerceptionFilter()],
139
+ entities: [
140
+ makePlayer('a'),
141
+ makeAI('guard', 'Guard', 'a', 1), // Even with terrible perception
142
+ ],
143
+ zones: [
144
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: [], light: 0 }, // Pitch dark
145
+ ],
146
+ });
147
+ engine.submitAction('attack', { targetIds: ['guard'] });
148
+ const cog = getCognition(engine.world, 'guard');
149
+ // Direct target ALWAYS knows (handled by cognition-core, not perception-filter)
150
+ expect(believes(cog, 'player', 'hostile', true)).toBe(true);
151
+ expect(cog.morale).toBeLessThan(70);
152
+ });
153
+ it('bystander with high perception sees combat details', () => {
154
+ const engine = createTestEngine({
155
+ modules: [traversalCore, combatCore, createCognitionCore(), createPerceptionFilter()],
156
+ entities: [
157
+ makePlayer('a'),
158
+ makeAI('target', 'Target', 'a', 5),
159
+ makeAI('bystander', 'Bystander', 'a', 10), // High perception
160
+ ],
161
+ zones: [
162
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: [], light: 10 }, // Bright
163
+ ],
164
+ });
165
+ engine.submitAction('attack', { targetIds: ['target'] });
166
+ const bystanderCog = getCognition(engine.world, 'bystander');
167
+ // High perception in bright room → should see combat
168
+ const combatMemories = getMemories(bystanderCog, 'saw-combat');
169
+ const dangerMemories = getMemories(bystanderCog, 'sensed-danger');
170
+ // Should have either saw-combat (high clarity) or sensed-danger (low clarity)
171
+ expect(combatMemories.length + dangerMemories.length).toBeGreaterThan(0);
172
+ expect(bystanderCog.suspicion).toBeGreaterThan(0);
173
+ });
174
+ it('bystander with low perception in dark zone misses combat', () => {
175
+ const engine = createTestEngine({
176
+ modules: [traversalCore, combatCore, createCognitionCore(), createPerceptionFilter()],
177
+ entities: [
178
+ makePlayer('a'),
179
+ makeAI('target', 'Target', 'a', 5),
180
+ makeAI('bystander', 'Bystander', 'a', 1), // Terrible perception
181
+ ],
182
+ zones: [
183
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: [], light: 0 }, // Pitch dark
184
+ ],
185
+ });
186
+ engine.submitAction('attack', { targetIds: ['target'] });
187
+ // Check bystander perception log
188
+ const log = getPerceptionLog(engine.world, 'bystander');
189
+ const visualEntries = log.filter((p) => p.sense === 'sight');
190
+ // In darkness with instinct=1:
191
+ // score = 7 + roll(1-50) = 8-57
192
+ // threshold for visual-combat = 20 + 10 (dark) = 30
193
+ // Some rolls may pass, some may fail
194
+ // But all entries should be logged
195
+ expect(log.length).toBeGreaterThan(0);
196
+ });
197
+ });
198
+ describe('Perception filter — cross-zone hearing', () => {
199
+ it('entity in adjacent zone hears combat', () => {
200
+ const engine = createTestEngine({
201
+ modules: [traversalCore, combatCore, createCognitionCore(), createPerceptionFilter()],
202
+ entities: [
203
+ makePlayer('a'),
204
+ makeAI('target', 'Target', 'a', 5),
205
+ makeAI('listener', 'Listener', 'b', 10), // High perception, adjacent zone
206
+ ],
207
+ zones: [
208
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'], light: 5 },
209
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 5 },
210
+ ],
211
+ });
212
+ engine.submitAction('attack', { targetIds: ['target'] });
213
+ const listenerCog = getCognition(engine.world, 'listener');
214
+ // Adjacent zone → auditory-combat layer (crossZone: true)
215
+ const heardCombat = getMemories(listenerCog, 'heard-combat');
216
+ const heardNoise = getMemories(listenerCog, 'heard-noise');
217
+ // Should have heard something from adjacent zone
218
+ expect(heardCombat.length + heardNoise.length).toBeGreaterThan(0);
219
+ });
220
+ it('entity in non-adjacent zone hears nothing', () => {
221
+ const engine = createTestEngine({
222
+ modules: [traversalCore, combatCore, createCognitionCore(), createPerceptionFilter()],
223
+ entities: [
224
+ makePlayer('a'),
225
+ makeAI('target', 'Target', 'a', 5),
226
+ makeAI('faraway', 'Far Away', 'c', 10), // Not adjacent to zone A
227
+ ],
228
+ zones: [
229
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'], light: 5 },
230
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a', 'c'], light: 5 },
231
+ { id: 'c', roomId: 'test', name: 'C', tags: [], neighbors: ['b'], light: 5 },
232
+ ],
233
+ });
234
+ engine.submitAction('attack', { targetIds: ['target'] });
235
+ const farawayCog = getCognition(engine.world, 'faraway');
236
+ // Zone C is NOT adjacent to zone A → no perception at all
237
+ expect(getMemories(farawayCog).length).toBe(0);
238
+ expect(getPerceptionLog(engine.world, 'faraway').length).toBe(0);
239
+ });
240
+ });
241
+ describe('Perception filter — custom layers', () => {
242
+ it('custom network sense layer detects digital events', () => {
243
+ const engine = createTestEngine({
244
+ modules: [
245
+ traversalCore,
246
+ createCognitionCore(),
247
+ createPerceptionFilter({
248
+ layers: [{
249
+ id: 'network-breach',
250
+ eventPatterns: ['netrunning.ice.breached'],
251
+ sense: 'network',
252
+ baseDifficulty: 20,
253
+ crossZone: true,
254
+ onPerceived(event, entity, clarity, world) {
255
+ const cog = getCognition(world, entity.id);
256
+ setBelief(cog, event.actorId, 'intruder', true, clarity, 'observed', event.tick);
257
+ },
258
+ }],
259
+ senseStats: { network: 'instinct' },
260
+ }),
261
+ ],
262
+ entities: [
263
+ makePlayer('a'),
264
+ makeAI('ice', 'ICE Sentry', 'b', 8),
265
+ ],
266
+ zones: [
267
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
268
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'] },
269
+ ],
270
+ });
271
+ // Manually emit a netrunning event (actorId must be top-level, not just in payload)
272
+ engine.store.emitEvent('netrunning.ice.breached', {
273
+ targetId: 'ice',
274
+ zoneId: 'b',
275
+ iceRemoved: 8,
276
+ }, { actorId: 'player' });
277
+ const iceCog = getCognition(engine.world, 'ice');
278
+ // ICE with instinct=8 in adjacent zone with crossZone=true should detect
279
+ // score = 8*7 + roll = 56 + roll(1-50) = 57-106
280
+ // threshold = 20 + 15 (adjacent) = 35
281
+ // Always detects
282
+ expect(believes(iceCog, 'player', 'intruder', true)).toBe(true);
283
+ });
284
+ });
285
+ describe('Perception filter — interpretation levels', () => {
286
+ it('high clarity perception gives full interpretation', () => {
287
+ const engine = createTestEngine({
288
+ modules: [traversalCore, createCognitionCore(), createPerceptionFilter()],
289
+ entities: [
290
+ makePlayer('a'),
291
+ makeAI('eagle', 'Eagle Eye', 'b', 10), // Maximum perception
292
+ ],
293
+ zones: [
294
+ { id: 'a', roomId: 'test', name: 'A', tags: [], neighbors: ['b'] },
295
+ { id: 'b', roomId: 'test', name: 'B', tags: [], neighbors: ['a'], light: 10 },
296
+ ],
297
+ });
298
+ engine.submitAction('move', { targetIds: ['b'] });
299
+ const log = getPerceptionLog(engine.world, 'eagle');
300
+ const visualEntry = log.find((p) => p.sense === 'sight');
301
+ expect(visualEntry).toBeDefined();
302
+ expect(visualEntry.detected).toBe(true);
303
+ // instinct=10, light=10 → score = 70 + roll, threshold = 30 - 10 = 20
304
+ // margin >= 50 → clarity = min(1, 0.5 + 50/30) = 1.0 → full
305
+ expect(visualEntry.interpretation).toBe('full');
306
+ });
307
+ });
308
+ //# sourceMappingURL=perception-filter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perception-filter.test.js","sourceRoot":"","sources":["../src/perception-filter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { EngineModule, WorldState, ResolvedEvent, EntityState } from '@ai-rpg-engine/core';
2
+ import type { ProgressionTreeDefinition, ProgressionNode, EffectDefinition } from '@ai-rpg-engine/content-schema';
3
+ export type ProgressionState = {
4
+ /** Currency balances: entityId → currencyId → amount */
5
+ currencies: Record<string, Record<string, number>>;
6
+ /** Unlocked nodes: entityId → treeId → nodeId[] */
7
+ unlocked: Record<string, Record<string, string[]>>;
8
+ };
9
+ export type ProgressionEvent = {
10
+ entityId: string;
11
+ type: 'currency-gained' | 'currency-spent' | 'node-unlocked';
12
+ treeId?: string;
13
+ nodeId?: string;
14
+ currencyId?: string;
15
+ amount?: number;
16
+ tick: number;
17
+ };
18
+ export type CurrencyReward = {
19
+ /** Event pattern to listen for (e.g. 'combat.entity.defeated') */
20
+ eventPattern: string;
21
+ /** Which currency to grant */
22
+ currencyId: string;
23
+ /** Amount to grant (or function of event payload) */
24
+ amount: number | ((event: ResolvedEvent, world: WorldState) => number);
25
+ /** Who receives the reward: 'actor' (event.actorId) or custom function */
26
+ recipient?: 'actor' | ((event: ResolvedEvent, world: WorldState) => string | undefined);
27
+ };
28
+ export type ProgressionCoreConfig = {
29
+ /** Progression trees (content definitions) */
30
+ trees?: ProgressionTreeDefinition[];
31
+ /** Automatic currency rewards from events */
32
+ rewards?: CurrencyReward[];
33
+ /** Effect handlers for progression node effects */
34
+ effectHandlers?: Record<string, EffectHandler>;
35
+ };
36
+ export type EffectHandler = (effect: EffectDefinition, entity: EntityState, world: WorldState) => void;
37
+ export type UnlockResult = {
38
+ success: boolean;
39
+ reason?: string;
40
+ event?: ProgressionEvent;
41
+ effects?: EffectDefinition[];
42
+ };
43
+ export declare function createProgressionCore(config?: ProgressionCoreConfig): EngineModule;
44
+ /** Get an entity's balance in a currency */
45
+ export declare function getCurrency(world: WorldState, entityId: string, currencyId: string): number;
46
+ /** Add currency to an entity */
47
+ export declare function addCurrency(world: WorldState, entityId: string, currencyId: string, amount: number, tick: number): void;
48
+ /** Spend currency (returns false if insufficient) */
49
+ export declare function spendCurrency(world: WorldState, entityId: string, currencyId: string, amount: number): boolean;
50
+ /** Get all unlocked nodes for an entity in a tree */
51
+ export declare function getUnlockedNodes(world: WorldState, entityId: string, treeId: string): string[];
52
+ /** Check if a specific node is unlocked */
53
+ export declare function isNodeUnlocked(world: WorldState, entityId: string, treeId: string, nodeId: string): boolean;
54
+ /** Check if a node can be unlocked (prerequisites met, currency available) */
55
+ export declare function canUnlock(world: WorldState, entityId: string, treeId: string, nodeId: string, trees: Map<string, ProgressionTreeDefinition>): {
56
+ can: boolean;
57
+ reason?: string;
58
+ };
59
+ /** Unlock a node: pay cost, record unlock, apply effects */
60
+ export declare function unlockNode(world: WorldState, entityId: string, treeId: string, nodeId: string, trees: Map<string, ProgressionTreeDefinition>, effectHandlers: Record<string, EffectHandler>, tick: number): UnlockResult;
61
+ /** Get all nodes available for unlock (prerequisites met, enough currency) */
62
+ export declare function getAvailableNodes(world: WorldState, entityId: string, treeId: string, trees: Map<string, ProgressionTreeDefinition>): ProgressionNode[];
63
+ //# sourceMappingURL=progression-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progression-core.d.ts","sourceRoot":"","sources":["../src/progression-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ // progression-core — flexible progression framework
2
+ // Supports XP/levels, milestones, reputation, skill-use growth, item upgrades.
3
+ // All models reduce to: earn currency → spend on tree nodes → get effects.
4
+ import { nextId } from '@ai-rpg-engine/core';
5
+ // --- Module ---
6
+ export function createProgressionCore(config) {
7
+ const trees = new Map();
8
+ for (const tree of config?.trees ?? []) {
9
+ trees.set(tree.id, tree);
10
+ }
11
+ const rewards = config?.rewards ?? [];
12
+ const effectHandlers = {
13
+ 'stat-boost': defaultStatBoost,
14
+ 'resource-boost': defaultResourceBoost,
15
+ 'grant-tag': defaultGrantTag,
16
+ 'set-global': defaultSetGlobal,
17
+ ...config?.effectHandlers,
18
+ };
19
+ return {
20
+ id: 'progression-core',
21
+ version: '0.1.0',
22
+ register(ctx) {
23
+ ctx.persistence.registerNamespace('progression-core', {
24
+ currencies: {},
25
+ unlocked: {},
26
+ });
27
+ // Register 'unlock' verb for spending currency on tree nodes
28
+ ctx.actions.registerVerb('unlock', (action, world) => {
29
+ const treeId = action.parameters?.treeId;
30
+ const nodeId = action.parameters?.nodeId;
31
+ if (!treeId || !nodeId) {
32
+ return [{
33
+ id: nextId('evt'),
34
+ tick: action.issuedAtTick,
35
+ type: 'progression.unlock.rejected',
36
+ actorId: action.actorId,
37
+ payload: { reason: 'missing treeId or nodeId' },
38
+ }];
39
+ }
40
+ const result = unlockNode(world, action.actorId, treeId, nodeId, trees, effectHandlers, action.issuedAtTick);
41
+ if (!result.success) {
42
+ return [{
43
+ id: nextId('evt'),
44
+ tick: action.issuedAtTick,
45
+ type: 'progression.unlock.rejected',
46
+ actorId: action.actorId,
47
+ payload: { treeId, nodeId, reason: result.reason },
48
+ }];
49
+ }
50
+ return [{
51
+ id: nextId('evt'),
52
+ tick: action.issuedAtTick,
53
+ type: 'progression.node.unlocked',
54
+ actorId: action.actorId,
55
+ payload: {
56
+ treeId,
57
+ nodeId,
58
+ effects: result.effects?.map((e) => e.type) ?? [],
59
+ },
60
+ }];
61
+ });
62
+ // Set up automatic currency rewards from events
63
+ for (const reward of rewards) {
64
+ ctx.events.on(reward.eventPattern, (event, world) => {
65
+ const recipientId = getRecipientId(reward, event, world);
66
+ if (!recipientId)
67
+ return;
68
+ const amount = typeof reward.amount === 'function'
69
+ ? reward.amount(event, world)
70
+ : reward.amount;
71
+ if (amount <= 0)
72
+ return;
73
+ addCurrency(world, recipientId, reward.currencyId, amount, event.tick);
74
+ });
75
+ }
76
+ },
77
+ };
78
+ }
79
+ // --- Currency Operations ---
80
+ function getProgressionState(world) {
81
+ return (world.modules['progression-core'] ?? { currencies: {}, unlocked: {} });
82
+ }
83
+ /** Get an entity's balance in a currency */
84
+ export function getCurrency(world, entityId, currencyId) {
85
+ const state = getProgressionState(world);
86
+ return state.currencies[entityId]?.[currencyId] ?? 0;
87
+ }
88
+ /** Add currency to an entity */
89
+ export function addCurrency(world, entityId, currencyId, amount, tick) {
90
+ const state = getProgressionState(world);
91
+ if (!state.currencies[entityId]) {
92
+ state.currencies[entityId] = {};
93
+ }
94
+ state.currencies[entityId][currencyId] = (state.currencies[entityId][currencyId] ?? 0) + amount;
95
+ }
96
+ /** Spend currency (returns false if insufficient) */
97
+ export function spendCurrency(world, entityId, currencyId, amount) {
98
+ const balance = getCurrency(world, entityId, currencyId);
99
+ if (balance < amount)
100
+ return false;
101
+ const state = getProgressionState(world);
102
+ state.currencies[entityId][currencyId] = balance - amount;
103
+ return true;
104
+ }
105
+ // --- Node Operations ---
106
+ /** Get all unlocked nodes for an entity in a tree */
107
+ export function getUnlockedNodes(world, entityId, treeId) {
108
+ const state = getProgressionState(world);
109
+ return state.unlocked[entityId]?.[treeId] ?? [];
110
+ }
111
+ /** Check if a specific node is unlocked */
112
+ export function isNodeUnlocked(world, entityId, treeId, nodeId) {
113
+ return getUnlockedNodes(world, entityId, treeId).includes(nodeId);
114
+ }
115
+ /** Check if a node can be unlocked (prerequisites met, currency available) */
116
+ export function canUnlock(world, entityId, treeId, nodeId, trees) {
117
+ const tree = trees.get(treeId);
118
+ if (!tree)
119
+ return { can: false, reason: `tree not found: ${treeId}` };
120
+ const node = tree.nodes.find((n) => n.id === nodeId);
121
+ if (!node)
122
+ return { can: false, reason: `node not found: ${nodeId}` };
123
+ // Already unlocked?
124
+ if (isNodeUnlocked(world, entityId, treeId, nodeId)) {
125
+ return { can: false, reason: 'already unlocked' };
126
+ }
127
+ // Check prerequisites
128
+ const unlocked = getUnlockedNodes(world, entityId, treeId);
129
+ if (node.requires?.length) {
130
+ const missing = node.requires.filter((r) => !unlocked.includes(r));
131
+ if (missing.length > 0) {
132
+ return { can: false, reason: `missing prerequisites: ${missing.join(', ')}` };
133
+ }
134
+ }
135
+ // Check currency
136
+ const balance = getCurrency(world, entityId, tree.currency);
137
+ if (balance < node.cost) {
138
+ return { can: false, reason: `insufficient ${tree.currency}: have ${balance}, need ${node.cost}` };
139
+ }
140
+ return { can: true };
141
+ }
142
+ /** Unlock a node: pay cost, record unlock, apply effects */
143
+ export function unlockNode(world, entityId, treeId, nodeId, trees, effectHandlers, tick) {
144
+ const check = canUnlock(world, entityId, treeId, nodeId, trees);
145
+ if (!check.can) {
146
+ return { success: false, reason: check.reason };
147
+ }
148
+ const tree = trees.get(treeId);
149
+ const node = tree.nodes.find((n) => n.id === nodeId);
150
+ // Pay the cost
151
+ if (!spendCurrency(world, entityId, tree.currency, node.cost)) {
152
+ return { success: false, reason: 'currency spend failed' };
153
+ }
154
+ // Record the unlock
155
+ const state = getProgressionState(world);
156
+ if (!state.unlocked[entityId]) {
157
+ state.unlocked[entityId] = {};
158
+ }
159
+ if (!state.unlocked[entityId][treeId]) {
160
+ state.unlocked[entityId][treeId] = [];
161
+ }
162
+ state.unlocked[entityId][treeId].push(nodeId);
163
+ // Apply effects
164
+ const entity = world.entities[entityId];
165
+ if (entity && node.effects.length > 0) {
166
+ for (const effect of node.effects) {
167
+ const handler = effectHandlers[effect.type];
168
+ if (handler) {
169
+ handler(effect, entity, world);
170
+ }
171
+ }
172
+ }
173
+ return {
174
+ success: true,
175
+ event: {
176
+ entityId,
177
+ type: 'node-unlocked',
178
+ treeId,
179
+ nodeId,
180
+ currencyId: tree.currency,
181
+ amount: node.cost,
182
+ tick,
183
+ },
184
+ effects: node.effects,
185
+ };
186
+ }
187
+ /** Get all nodes available for unlock (prerequisites met, enough currency) */
188
+ export function getAvailableNodes(world, entityId, treeId, trees) {
189
+ const tree = trees.get(treeId);
190
+ if (!tree)
191
+ return [];
192
+ return tree.nodes.filter((node) => {
193
+ const check = canUnlock(world, entityId, treeId, node.id, trees);
194
+ return check.can;
195
+ });
196
+ }
197
+ // --- Default Effect Handlers ---
198
+ function defaultStatBoost(effect, entity) {
199
+ const statId = effect.params.stat;
200
+ const amount = effect.params.amount;
201
+ if (statId && amount) {
202
+ entity.stats[statId] = (entity.stats[statId] ?? 0) + amount;
203
+ }
204
+ }
205
+ function defaultResourceBoost(effect, entity) {
206
+ const resourceId = effect.params.resource;
207
+ const amount = effect.params.amount;
208
+ if (resourceId && amount) {
209
+ entity.resources[resourceId] = (entity.resources[resourceId] ?? 0) + amount;
210
+ }
211
+ }
212
+ function defaultGrantTag(effect, entity) {
213
+ const tag = effect.params.tag;
214
+ if (tag && !entity.tags.includes(tag)) {
215
+ entity.tags.push(tag);
216
+ }
217
+ }
218
+ function defaultSetGlobal(effect, _entity, world) {
219
+ const key = effect.params.key;
220
+ const value = effect.params.value;
221
+ if (key && value !== undefined) {
222
+ world.globals[key] = value;
223
+ }
224
+ }
225
+ // --- Helpers ---
226
+ function getRecipientId(reward, event, world) {
227
+ if (!reward.recipient || reward.recipient === 'actor') {
228
+ return event.actorId;
229
+ }
230
+ return reward.recipient(event, world);
231
+ }
232
+ //# sourceMappingURL=progression-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progression-core.js","sourceRoot":"","sources":["../src/progression-core.ts"],"names":[],"mappings":"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"}