rpg-event-generator 3.1.1 → 4.0.1

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 (66) hide show
  1. package/README.md +48 -298
  2. package/demo.js +75 -1055
  3. package/dist/RPGEventGenerator.d.ts +24 -2
  4. package/dist/RPGEventGenerator.d.ts.map +1 -1
  5. package/dist/RPGEventGenerator.js +47 -21
  6. package/dist/RPGEventGenerator.js.map +1 -1
  7. package/dist/chains/ChainSystem.js +1 -1
  8. package/dist/chains/index.js +1 -1
  9. package/dist/core/ContextAnalyzer.js +1 -1
  10. package/dist/core/DifficultyScaler.js +1 -1
  11. package/dist/core/GeneratorCore.d.ts +19 -112
  12. package/dist/core/GeneratorCore.d.ts.map +1 -1
  13. package/dist/core/GeneratorCore.js +1817 -1437
  14. package/dist/core/GeneratorCore.js.map +1 -1
  15. package/dist/core/MarkovEngine.js +1 -1
  16. package/dist/core/index.js +1 -1
  17. package/dist/database/MemoryDatabaseAdapter.js +1 -1
  18. package/dist/database/TemplateDatabase.js +1 -1
  19. package/dist/environment/EnvironmentalSystem.d.ts +2 -0
  20. package/dist/environment/EnvironmentalSystem.d.ts.map +1 -1
  21. package/dist/environment/EnvironmentalSystem.js +46 -10
  22. package/dist/environment/EnvironmentalSystem.js.map +1 -1
  23. package/dist/environment/index.js +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/interfaces/systems.d.ts +1 -1
  26. package/dist/interfaces/systems.d.ts.map +1 -1
  27. package/dist/localization/LocalizationSystem.js +1 -1
  28. package/dist/localization/index.js +1 -1
  29. package/dist/relationships/RelationshipSystem.js +1 -1
  30. package/dist/relationships/index.js +1 -1
  31. package/dist/rules/RuleEngine.js +1 -1
  32. package/dist/rules/index.js +1 -1
  33. package/dist/src/types/world.d.ts +9 -0
  34. package/dist/src/types/world.d.ts.map +1 -1
  35. package/dist/templates/TemplateSystem.js +1 -1
  36. package/dist/templates/index.js +1 -1
  37. package/dist/time/TimeSystem.js +1 -1
  38. package/dist/time/index.js +1 -1
  39. package/dist/types/world.d.ts +9 -0
  40. package/dist/types/world.d.ts.map +1 -1
  41. package/dist/utils/array.js +1 -1
  42. package/dist/utils/constants.js +1 -1
  43. package/dist/utils/file.js +1 -1
  44. package/dist/utils/index.d.ts +1 -0
  45. package/dist/utils/index.d.ts.map +1 -1
  46. package/dist/utils/index.js +2 -1
  47. package/dist/utils/index.js.map +1 -1
  48. package/dist/utils/random.js +1 -1
  49. package/dist/utils/text.js +1 -1
  50. package/dist/utils/validation.js +1 -1
  51. package/dist/utils/version.d.ts +8 -0
  52. package/dist/utils/version.d.ts.map +1 -0
  53. package/dist/utils/version.js +11 -0
  54. package/dist/utils/version.js.map +1 -0
  55. package/dist/world/WorldBuildingSystem.d.ts +16 -2
  56. package/dist/world/WorldBuildingSystem.d.ts.map +1 -1
  57. package/dist/world/WorldBuildingSystem.js +357 -155
  58. package/dist/world/WorldBuildingSystem.js.map +1 -1
  59. package/dist/world/index.d.ts +1 -1
  60. package/dist/world/index.d.ts.map +1 -1
  61. package/dist/world/index.js.map +1 -1
  62. package/dist/world/worldContent.d.ts +13 -0
  63. package/dist/world/worldContent.d.ts.map +1 -0
  64. package/dist/world/worldContent.js +109 -0
  65. package/dist/world/worldContent.js.map +1 -0
  66. package/package.json +1 -1
package/demo.js CHANGED
@@ -1,1058 +1,78 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * Quick smoke demo — Tier 1 core + a taste of world lore.
4
+ * For copy-paste examples and Tier 2/3 guides, see typedoc-pages/examples.md
5
+ * (built to docs/documents/Examples.html via npm run docs).
6
+ */
2
7
 
3
- const { RPGEventGenerator } = require('./dist/index.js');
4
-
5
- const DEMO_CONFIG = {
6
- version: '3.0.2',
7
- showErrors: true,
8
- pauseBetweenDemos: false
9
- };
10
- function printHeader(title, version = '') {
11
- console.log('\n' + '='.repeat(50));
12
- console.log(`${title}${version ? ` (${version})` : ''}`);
13
- console.log('='.repeat(50));
14
- }
15
-
16
- function printSection(title) {
17
- console.log(`\n${title}`);
18
- console.log('-'.repeat(title.length));
19
- }
20
-
21
- function printResult(label, value) {
22
- console.log(`${label}: ${value}`);
23
- }
24
-
25
- function safeExecute(fn, description) {
8
+ function loadPackage() {
26
9
  try {
27
- return fn();
28
- } catch (error) {
29
- if (DEMO_CONFIG.showErrors) {
30
- console.error(`❌ Error in ${description}:`, error.message);
31
- }
32
- return null;
33
- }
34
- }
35
-
36
- console.log(`🎲 RPG Event Generator ${DEMO_CONFIG.version} - Complete Feature Showcase`);
37
- console.log('=' .repeat(60));
38
-
39
- // Basic Event Generation
40
- function demoBasicEventGeneration() {
41
- printSection('⚡ Demo 1: Basic Event Generation');
42
-
43
- const generator = new RPGEventGenerator();
44
- const event = safeExecute(() => generator.generateEvent(), 'basic event generation');
45
-
46
- if (event) {
47
- printResult('Basic Event', event.title);
48
- printResult('Type', `${event.type}, Difficulty: ${event.difficulty}`);
49
- printResult('Choices', `${event.choices.length} options`);
50
- printResult('Sample choice', `"${event.choices[0].text}"`);
51
- }
52
- }
53
-
54
- // Dynamic Difficulty Scaling
55
- function demoDynamicDifficultyScaling() {
56
- printSection('📊 Demo 2: Dynamic Difficulty Scaling');
57
-
58
- const generator = new RPGEventGenerator();
59
-
60
- const weakling = {
61
- gold: 50,
62
- influence: 10,
63
- skills: { combat: 20 }
64
- };
65
-
66
- const hero = {
67
- gold: 50000,
68
- influence: 500,
69
- skills: { combat: 100, diplomacy: 80 },
70
- relationships: [{ name: 'King', type: 'ally', relationship: 80 }]
71
- };
72
-
73
- const easyEvent = safeExecute(() => generator.generateEvent(weakling), 'weak character event');
74
- const hardEvent = safeExecute(() => generator.generateEvent(hero), 'powerful character event');
75
-
76
- if (easyEvent) printResult('Weak character event', `${easyEvent.title} (${easyEvent.difficulty})`);
77
- if (hardEvent) printResult('Powerful character event', `${hardEvent.title} (${hardEvent.difficulty})`);
78
- }
79
-
80
- // Context-Aware Events
81
- function demoContextAwareEvents() {
82
- printSection('🎯 Demo 3: Context-Aware Events');
83
-
84
- const generator = new RPGEventGenerator();
85
-
86
- const playerContext = {
87
- age: 35,
88
- gold: 2500,
89
- influence: 40,
90
- reputation: 25,
91
- career: 'noble',
92
- skills: { diplomacy: 70, combat: 45, intrigue: 30 },
93
- relationships: [
94
- { name: 'Lord Harrington', type: 'ally', relationship: 60 }
95
- ],
96
- location: 'capital',
97
- season: 'winter'
98
- };
99
-
100
- const event = safeExecute(() => generator.generateEvent(playerContext), 'context-aware event');
101
-
102
- if (event) {
103
- printResult('Context-aware event', event.title);
104
- printResult('Generated for', `${playerContext.career} in ${playerContext.location} during ${playerContext.season}`);
105
- }
106
- }
107
-
108
- // Custom Training Data
109
- function demoCustomTrainingData() {
110
- printSection('📚 Demo 4: Custom Training Data');
111
-
112
- const generator = new RPGEventGenerator();
113
-
114
- const trainingData = [
115
- 'The ancient dragon hoards glittering treasures in its mountain lair',
116
- 'Mystical runes glow with ethereal blue light in the dark chamber',
117
- 'The enchanted forest whispers secrets to those who listen carefully',
118
- 'Crystal caverns sparkle with magical energy and hidden dangers'
119
- ];
120
-
121
- safeExecute(() => generator.addTrainingData(trainingData), 'adding training data');
122
-
123
- const event = safeExecute(() => generator.generateEvent(), 'custom training event');
124
-
125
- if (event) {
126
- printResult('Custom training event', event.title);
127
- printResult('Description', `${event.description.substring(0, 100)}...`);
128
- }
129
- }
130
-
131
- // Modular Event System
132
- function demoModularEventSystem() {
133
- printSection('🧩 Demo 5: Modular Event System');
134
-
135
- const generator = new RPGEventGenerator();
136
-
137
- const customTemplate = {
138
- title: 'Mystic Vision',
139
- narrative: 'You experience a vivid prophetic dream showing future events.',
140
- choices: [
141
- {
142
- text: 'Seek out the prophecy',
143
- effect: { wisdom: 15, risk: 20 },
144
- consequence: 'visionary'
145
- },
146
- {
147
- text: 'Dismiss it as a dream',
148
- effect: { stress: -10 },
149
- consequence: 'skeptical'
150
- }
151
- ]
152
- };
153
-
154
- const mysticalTraining = [
155
- 'The ancient prophecy foretells of great change',
156
- 'Mystic visions reveal hidden truths to the worthy',
157
- 'Dreams of the future guide the destinies of heroes'
158
- ];
159
-
160
- safeExecute(() => generator.registerEventTemplate('MYSTIC_VISION', customTemplate), 'registering template');
161
- safeExecute(() => generator.addCustomTrainingData(mysticalTraining, 'mystical'), 'adding mystical training');
162
-
163
- const event = safeExecute(() => generator.generateEvent(), 'modular event generation');
164
- if (event) {
165
- printResult('Modular system event', event.title);
166
- }
167
-
168
- const exportedContent = safeExecute(() => generator.exportCustomContent(), 'exporting content');
169
- if (exportedContent) {
170
- printResult('Exported templates', Object.keys(exportedContent.templates).length);
171
- }
172
-
173
- const newGenerator = new RPGEventGenerator();
174
- const importResult = safeExecute(() => newGenerator.importCustomContent(exportedContent), 'importing content');
175
- if (importResult) {
176
- printResult('Imported templates', importResult.templates.success);
177
- }
178
- }
179
-
180
- function demoEventChains() {
181
- printSection('⛓️ Demo 6: Event Chains');
182
-
183
- const generator = new RPGEventGenerator();
184
-
185
- const chainResult = safeExecute(() => generator.startChain('BANDIT_RISING'), 'starting event chain');
186
-
187
- if (chainResult) {
188
- printResult('Started chain', chainResult.title);
189
- console.log('Available choices in this event lead to different consequences...');
190
-
191
- const nextEvent = safeExecute(() => generator.advanceChain(chainResult.chainId, 'bandit'), 'advancing chain');
192
-
193
- if (nextEvent) {
194
- printResult('Chain advanced', nextEvent.title);
195
- } else {
196
- console.log('Chain could not advance - need to choose \'bandit\' consequence first');
197
- }
198
-
199
- const activeChains = safeExecute(() => generator.getActiveChains(), 'getting active chains');
200
- if (activeChains) {
201
- printResult('Active chains', activeChains.length);
202
- }
203
- }
204
- }
205
-
206
-
207
- function demoTimeBasedEvents() {
208
- printSection('⏰ Demo 7: Time-Based Events');
209
-
210
- const generator = new RPGEventGenerator();
211
-
212
- const dueEvents = safeExecute(() => generator.advanceGameDay(), 'advancing game day');
213
- const currentTime = safeExecute(() => generator.getCurrentTime(), 'getting current time');
214
-
215
- if (currentTime) {
216
- printResult('Advanced to', `day ${currentTime.day}, season: ${currentTime.season}`);
217
- }
218
-
219
- safeExecute(() => generator.startTimeBasedChain('POLITICAL_UPRISING'), 'starting time-based chain');
220
-
221
- const activeTimeChains = safeExecute(() => generator.getActiveTimeChains(), 'getting active time chains');
222
- if (activeTimeChains) {
223
- printResult('Active time-based chains', activeTimeChains.length);
224
- }
225
-
226
- const timeEvent = safeExecute(() => generator.generateTimeAwareEvent({ season: 'spring' }), 'generating time-aware event');
227
- if (timeEvent) {
228
- printResult('Season-aware event', timeEvent.title);
229
- }
230
- }
231
-
232
- function demoGameStateManagement() {
233
- printSection('💾 Demo 8: Game State Management');
234
-
235
- const generator = new RPGEventGenerator();
236
-
237
- const gameState = {
238
- player: { level: 5, gold: 1000 },
239
- completedEvents: new Set(['tutorial']),
240
- currentDay: 10
241
- };
242
-
243
- safeExecute(() => generator.loadGameState(gameState), 'loading game state');
244
-
245
- const savedState = safeExecute(() => generator.getGameState(), 'getting game state');
246
-
247
- if (savedState) {
248
- console.log('Game state loaded and saved successfully');
249
- printResult('Current day', `${savedState.timeSystem.currentDay}, Season: ${savedState.timeSystem.currentSeason}`);
250
- printResult('Active chains', savedState.activeChains.length);
251
- }
252
- }
253
-
254
- // Multi-Language Support
255
- function demoMultiLanguageSupport() {
256
-
257
- const generator = new RPGEventGenerator({
258
- enableDatabase: false,
259
- enableModifiers: true,
260
- enableRelationships: true,
261
- enableDependencies: true,
262
- language: 'en'
263
- });
264
-
265
- printSection('🌍 Demo 9: Multi-Language Support');
266
-
267
- const spanishPack = {
268
- ui: {
269
- 'event.title.default': 'Evento Inesperado',
270
- 'choice.fight': 'Luchar',
271
- 'choice.flee': 'Huir',
272
- 'choice.negotiate': 'Negociar'
273
- },
274
- culture: {
275
- nameFormats: ['western'],
276
- currencySymbols: ['oro']
277
- }
278
- };
279
-
280
- const frenchPack = {
281
- ui: {
282
- 'event.title.default': 'Événement Inattendu',
283
- 'choice.fight': 'Combattre',
284
- 'choice.flee': 'Fuire',
285
- 'choice.negotiate': 'Négocier'
286
- }
287
- };
288
-
289
- safeExecute(() => generator.loadLanguagePack('es', spanishPack), 'loading Spanish pack');
290
- safeExecute(() => generator.loadLanguagePack('fr', frenchPack), 'loading French pack');
291
-
292
- printResult('English', generator.translate('choice.fight'));
293
-
294
- safeExecute(() => generator.setLanguage('es'), 'switching to Spanish');
295
- printResult('Spanish', generator.translate('choice.fight'));
296
-
297
- safeExecute(() => generator.setLanguage('fr'), 'switching to French');
298
- printResult('French', generator.translate('choice.fight'));
299
-
300
- safeExecute(() => generator.setLanguage('en'), 'switching back to English');
301
-
302
- return generator;
303
- }
304
-
305
- // Environmental Modifiers
306
- function demoEnvironmentalModifiers(generator) {
307
- printSection('🌤️ Demo 10: Environmental Modifiers');
308
-
309
- console.log('Individual Modifiers:');
310
-
311
- safeExecute(() => generator.setEnvironmentalContext({ weather: 'rain' }), 'setting rain context');
312
- const rainEvent = safeExecute(() => generator.generateEnhancedEvent(), 'generating rain event');
313
- if (rainEvent) {
314
- printResult('Rain Event', rainEvent.title);
315
- printResult('Description contains atmospheric text', rainEvent.description.includes('gloomy'));
316
- }
317
-
318
- safeExecute(() => generator.setEnvironmentalContext({ season: 'winter' }), 'setting winter context');
319
- const winterEvent = safeExecute(() => generator.generateEnhancedEvent(), 'generating winter event');
320
- if (winterEvent) {
321
- printResult('Winter Event', winterEvent.title);
322
- printResult('Description contains seasonal text', winterEvent.description.includes('bleak'));
323
- }
324
-
325
- console.log('\nCombined Modifiers:');
326
- const testEvent = {
327
- title: 'Test Event',
328
- description: 'Testing modifier effects.',
329
- choices: [{
330
- text: 'Continue',
331
- effect: { health: 10, gold: 50 }
332
- }]
333
- };
334
-
335
- safeExecute(() => generator.setEnvironmentalContext({ weather: 'storm', season: 'winter' }), 'setting storm+winter context');
336
- const modifiedEvent = safeExecute(() => generator.applyModifiers(testEvent), 'applying modifiers');
337
-
338
- if (modifiedEvent) {
339
- printResult('Original health', testEvent.choices[0].effect.health);
340
- printResult('Modified health', `${modifiedEvent.choices[0].effect.health} (storm: -5, winter: *1.5 = 7)`);
341
- printResult('Modified gold', `${modifiedEvent.choices[0].effect.gold} (unchanged)`);
342
- }
343
- }
344
-
345
- function demoEventDependencies(generator) {
346
- printSection('🔗 Demo 11: Event Dependencies');
347
-
348
- safeExecute(() => generator.registerEventDependency('ROYAL_BALL', {
349
- type: 'event_completed',
350
- eventId: 'COURT_INTRODUCTION'
351
- }), 'registering simple dependency');
352
-
353
- safeExecute(() => generator.registerEventDependency('ELITE_MISSION', {
354
- operator: 'AND',
355
- conditions: [
356
- { type: 'stat_requirement', stat: 'level', min: 10 },
357
- { type: 'event_completed', eventId: 'BASIC_TRAINING' },
358
- { type: 'stat_requirement', stat: 'reputation', min: 50 }
359
- ]
360
- }), 'registering AND dependency');
361
-
362
- safeExecute(() => generator.registerEventDependency('SOCIAL_EVENT', {
363
- operator: 'OR',
364
- conditions: [
365
- { type: 'stat_requirement', stat: 'reputation', min: 75 },
366
- { type: 'stat_requirement', stat: 'gold', min: 1000 },
367
- { type: 'relationship_requirement', npc: 'nobleman', min: 60 }
368
- ]
369
- }), 'registering OR dependency');
370
- const dependencyGameState = {
371
- completedEvents: new Set(['COURT_INTRODUCTION', 'BASIC_TRAINING']),
372
- player: { level: 12, reputation: 80, gold: 500 }
373
- };
374
-
375
- console.log('Dependency Checks:');
376
- const royalBall = safeExecute(() => generator.checkEventDependencies('ROYAL_BALL', dependencyGameState), 'checking royal ball');
377
- const eliteMission = safeExecute(() => generator.checkEventDependencies('ELITE_MISSION', dependencyGameState), 'checking elite mission');
378
- const socialEvent = safeExecute(() => generator.checkEventDependencies('SOCIAL_EVENT', dependencyGameState), 'checking social event');
379
-
380
- printResult('Can access Royal Ball', royalBall);
381
- printResult('Can access Elite Mission', eliteMission);
382
- printResult('Can access Social Event', socialEvent);
383
- }
384
-
385
- function demoNPCRelationships(generator) {
386
- printSection('👥 Demo 12: NPC Relationships');
387
-
388
- safeExecute(() => generator.addNPC({
389
- id: 'merchant_sam',
390
- name: 'Merchant Sam',
391
- type: 'merchant'
392
- }), 'adding merchant NPC');
393
-
394
- safeExecute(() => generator.addNPC({
395
- id: 'guard_captain',
396
- name: 'Captain Valeria',
397
- type: 'guard'
398
- }), 'adding guard NPC');
399
-
400
- safeExecute(() => generator.addNPC({
401
- id: 'nobleman',
402
- name: 'Lord Harrington',
403
- type: 'noble'
404
- }), 'adding noble NPC');
405
-
406
- console.log('Relationship Interactions:');
407
-
408
- const initialSamRel = safeExecute(() => generator.getRelationship('merchant_sam', 'player'), 'getting initial relationship');
409
- printResult('Initial relationship with Merchant Sam', initialSamRel?.strength || 0);
410
-
411
- safeExecute(() => generator.applyRelationshipRule('merchant_sam', 'player', 'save_life'), 'applying save_life rule');
412
- const samRelAfter = safeExecute(() => generator.getRelationship('merchant_sam', 'player'), 'getting relationship after save');
413
- printResult('After saving life', samRelAfter?.strength || 0);
414
-
415
- safeExecute(() => generator.updateRelationship('guard_captain', 'player', -15, 'minor dispute'), 'updating guard relationship');
416
- const guardRel = safeExecute(() => generator.getRelationship('guard_captain', 'player'), 'getting guard relationship');
417
- printResult('Guard Captain relationship', guardRel?.strength || 0);
418
-
419
- safeExecute(() => generator.applyRelationshipRule('nobleman', 'player', 'help_combat'), 'applying help_combat rule');
420
- const nobleRel = safeExecute(() => generator.getRelationship('nobleman', 'player'), 'getting noble relationship');
421
- printResult('Nobleman relationship', nobleRel?.strength || 0);
422
-
423
- const samSummary = safeExecute(() => generator.getRelationshipSummary('merchant_sam'), 'getting relationship summary');
424
- if (samSummary) {
425
- console.log(`\nMerchant Sam has ${samSummary.totalRelationships} relationships`);
426
- printResult('Average relationship strength', samSummary.averageStrength.toFixed(1));
427
- }
428
- }
429
-
430
- function demoCombinedFeatures(generator) {
431
- printSection('🎭 Demo 13: Combined Feature Usage');
432
-
433
- const comprehensiveContext = {
434
- player: {
435
- id: 'player',
436
- level: 15,
437
- reputation: 70,
438
- gold: 2000
439
- },
440
- environment: {
441
- weather: 'rain',
442
- season: 'spring',
443
- timeOfDay: 'dawn'
444
- },
445
- gameState: {
446
- completedEvents: new Set(['TUTORIAL', 'FIRST_QUEST']),
447
- relationships: {
448
- merchant_sam: { strength: 45, type: 'friend' }
449
- }
450
- }
451
- };
452
-
453
- console.log('Generating event with ALL features combined:');
454
- const comprehensiveEvent = safeExecute(() => generator.generateEnhancedEvent(comprehensiveContext), 'generating comprehensive event');
455
-
456
- if (comprehensiveEvent) {
457
- printResult('Title', comprehensiveEvent.title);
458
- printResult('Description', comprehensiveEvent.description.substring(0, 60) + '...');
459
- printResult('Type', comprehensiveEvent.type);
460
- printResult('Difficulty', comprehensiveEvent.difficulty);
461
- printResult('Choices', comprehensiveEvent.choices.length);
462
-
463
- // Show choice details
464
- console.log('\nChoice Details:');
465
- comprehensiveEvent.choices.slice(0, 2).forEach((choice, i) => {
466
- console.log(` ${i + 1}. ${choice.text}`);
467
- if (choice.effect.gold) console.log(` Gold effect: ${choice.effect.gold > 0 ? '+' : ''}${choice.effect.gold}`);
468
- if (choice.effect.reputation) console.log(` Reputation effect: ${choice.effect.reputation > 0 ? '+' : ''}${choice.effect.reputation}`);
469
- });
470
-
471
- // Show tags applied by rules
472
- if (comprehensiveEvent.tags && comprehensiveEvent.tags.length > 0) {
473
- printResult('Applied Tags', comprehensiveEvent.tags.join(', '));
474
- }
475
-
476
- // Show AI enhancement status
477
- const hasAIEnhancement = comprehensiveEvent.tags?.includes('ai-enhanced');
478
- printResult('AI Enhanced', hasAIEnhancement ? 'Yes' : 'No');
479
-
480
- // Show environmental context effects
481
- printResult('Weather Context', comprehensiveContext.environment.weather);
482
- printResult('Season Context', comprehensiveContext.environment.season);
483
- printResult('Time Context', comprehensiveContext.environment.timeOfDay);
484
-
485
- // Show relationship effects
486
- const merchantRelationship = comprehensiveContext.gameState.relationships.merchant_sam;
487
- printResult('Merchant Relationship', `${merchantRelationship.type} (${merchantRelationship.strength})`);
488
-
489
- console.log('\nFeature Integration Status:');
490
- console.log(' ✅ Enhanced Procedural Generation (Markov + Context)');
491
- console.log(' ✅ Dynamic Difficulty Scaling');
492
- console.log(' ✅ Environmental Effects');
493
- console.log(' ✅ Relationship-Based Events');
494
- console.log(' ✅ Rule Engine Processing');
495
- console.log(' ✅ Optional AI Enhancement');
496
- console.log(' ✅ Template System Integration');
497
- console.log(' ✅ Time-Based Event Logic');
498
- }
499
- }
500
-
501
- // Backward Compatibility
502
- function demoBackwardCompatibility() {
503
- printSection('🔄 Demo 14: Backward Compatibility');
504
-
505
- const legacyGenerator = new RPGEventGenerator();
506
- const legacyEvent = safeExecute(() => legacyGenerator.generateEvent(), 'legacy generator test');
507
- if (legacyEvent) {
508
- printResult('Basic generator works', legacyEvent.title);
509
- }
510
-
511
- const partialGenerator = new RPGEventGenerator({
512
- enableDatabase: false,
513
- enableModifiers: false,
514
- enableRelationships: true,
515
- enableDependencies: false
516
- });
517
- const partialEvent = safeExecute(() => partialGenerator.generateEvent(), 'partial features test');
518
- if (partialEvent) {
519
- printResult('Partial features work', partialEvent.title);
520
- }
521
-
522
- }
523
-
524
- function demoSystemStatus(generator) {
525
- printSection('📊 Demo 15: System Status');
526
-
527
- const status = safeExecute(() => generator.getSystemStatus(), 'getting system status');
528
-
529
- if (status) {
530
- printResult('Current language', status.language);
531
- printResult('Available languages', status.availableLanguages.join(', '));
532
- printResult('Modifiers enabled', status.modifiersEnabled);
533
- printResult('Relationships enabled', status.relationshipsEnabled);
534
- printResult('Dependencies enabled', status.dependenciesEnabled);
535
- printResult('Total NPCs', status.totalNPCs);
536
- }
537
- }
538
-
539
- // Advanced Usage Examples
540
- function demoAdvancedUsage(generator) {
541
- printSection('🎯 Demo 16: Advanced Usage Examples');
542
-
543
- safeExecute(() => generator.registerModifier('festival', {
544
- type: 'event',
545
- effects: { mood_bonus: 20 },
546
- text_modifiers: {
547
- atmosphere: 'festive',
548
- add_descriptors: ['celebratory', 'joyful']
549
- }
550
- }), 'registering custom modifier');
551
-
552
- console.log('Time progression:');
553
- safeExecute(() => generator.advanceTime(30), 'advancing time 30 days');
554
- const currentSeason = safeExecute(() => generator.timeSystem?.currentSeason, 'getting current season');
555
- if (currentSeason) {
556
- printResult('New season', currentSeason);
557
- }
558
-
559
- const network = safeExecute(() => generator.getRelationshipNetwork('merchant_sam', 2), 'getting relationship network');
560
- if (network) {
561
- printResult('Merchant Sam\'s relationship network', `${network.nodes.size} nodes, ${network.edges.length} connections`);
562
- }
563
- }
564
-
565
- async function runDemo() {
566
-
567
- demoBasicEventGeneration();
568
- demoDynamicDifficultyScaling();
569
- demoContextAwareEvents();
570
- demoCustomTrainingData();
571
- demoModularEventSystem();
572
- demoEventChains();
573
- demoTimeBasedEvents();
574
- demoGameStateManagement();
575
-
576
- const enhancedGenerator = demoMultiLanguageSupport();
577
- demoEnvironmentalModifiers(enhancedGenerator);
578
- demoEventDependencies(enhancedGenerator);
579
- demoNPCRelationships(enhancedGenerator);
580
- demoCombinedFeatures(enhancedGenerator);
581
- demoBackwardCompatibility();
582
- demoSystemStatus(enhancedGenerator);
583
- demoAdvancedUsage(enhancedGenerator);
584
-
585
- printHeader('🚀 v2.0.0 FEATURE DEMOS');
586
-
587
- // v2.0.0 Feature Demos
588
- demoAdvancedTemplates();
589
- demoWorldBuilding();
590
- demoPerformanceOptimizations();
591
- await demoDatabaseIntegration();
592
- demoCustomRuleEngine();
593
- demoThemeCreator();
594
- demoPureMarkovMode();
595
- demoEventEconomy();
596
-
597
- printHeader('✅ DEMO COMPLETE');
598
- console.log('🎉 All v2.0.0 features demonstrated successfully!');
599
- console.log('📦 Version 2.0.0 delivers revolutionary new capabilities with full backward compatibility.');
600
- console.log('🚀 Production-ready for game development!');
601
- }
602
-
603
- // v2.0.0 Feature Demos
604
- function demoCustomRuleEngine() {
605
- printSection('🧠 Demo 26: Custom Rule Engine (v2.0.0)');
606
-
607
- const generator = new RPGEventGenerator({ enableRuleEngine: true, enableDatabase: false });
608
-
609
- // Create a custom rule for wealthy players
610
- const wealthyRule = {
611
- conditions: [
612
- { type: 'stat_greater_than', params: { stat: 'gold', value: 1000 } }
613
- ],
614
- effects: {
615
- modifyChoices: {
616
- multiply: { gold: 1.3 },
617
- add: { reputation: 5 }
618
- },
619
- addTags: ['wealthy_player_bonus']
620
- }
621
- };
622
-
623
- safeExecute(() => {
624
- generator.addCustomRule('wealthy_bonus', wealthyRule);
625
- printResult('Rule added', 'wealthy_bonus');
626
-
627
- // Test with wealthy player
628
- const wealthyEvent = generator.generateEvent({ gold: 2000 });
629
- printResult('Wealthy player event', wealthyEvent.title);
630
- printResult('Tags applied', wealthyEvent.tags?.join(', ') || 'none');
631
-
632
- // Test with poor player
633
- const poorEvent = generator.generateEvent({ gold: 100 });
634
- printResult('Poor player event', poorEvent.title);
635
- printResult('Tags applied', poorEvent.tags?.join(', ') || 'none');
636
-
637
- printResult('Active rules', Object.keys(generator.getCustomRules()).length);
638
- }, 'custom rule engine');
639
- }
640
-
641
- function demoThemeCreator() {
642
- printSection('🎨 Demo 27: Theme Creator (v2.0.0)');
643
-
644
- const customTrainingData = [
645
- 'Neon-lit cantinas pulse with quantum energy',
646
- 'Robotic bartenders serve drinks that change your memories',
647
- 'Space cowboys duel with laser revolvers under three moons',
648
- 'Alien merchants haggle over crystalline data cores',
649
- 'Floating colonies drift through asteroid fields'
650
- ];
651
-
652
- safeExecute(() => {
653
- const generator = new RPGEventGenerator({
654
- enableDatabase: false,
655
- trainingData: customTrainingData,
656
- theme: 'space-opera',
657
- culture: 'cyberpunk'
658
- });
659
-
660
- const event = generator.generateEvent();
661
- printResult('Custom theme event', event.title);
662
- printResult('Description preview', event.description.substring(0, 80) + '...');
663
- printResult('Training sentences used', customTrainingData.length);
664
- }, 'theme creator');
665
- }
666
-
667
- function demoPureMarkovMode() {
668
- printSection('🎲 Demo 28: Pure Markov Mode (v2.0.0)');
669
-
670
- const pureTrainingData = [
671
- 'Crystal caves echo with ancient magical resonances',
672
- 'Shadowy figures emerge from fog-shrouded forests',
673
- 'Forgotten ruins hide treasures and eldritch horrors',
674
- 'Mysterious merchants offer artifacts of power',
675
- 'Wandering bards sing tales of lost civilizations'
676
- ];
677
-
678
- safeExecute(() => {
679
- const pureGenerator = new RPGEventGenerator({
680
- enableDatabase: false,
681
- trainingData: pureTrainingData,
682
- pureMarkovMode: true,
683
- enableTemplates: false
684
- });
685
-
686
- const event = pureGenerator.generateEvent();
687
- printResult('Pure Markov event', event.title);
688
- printResult('Type', event.type);
689
- printResult('Generated purely from', `${pureTrainingData.length} custom sentences`);
690
- printResult('Templates disabled', 'true (Pure Markov only)');
691
- }, 'pure Markov mode');
692
- }
693
-
694
- function demoAdvancedTemplates() {
695
- printSection('🎨 Demo 19: Advanced Template System (v2.0.0)');
696
-
697
- const generator = new RPGEventGenerator();
698
-
699
- // Create base templates for inheritance
700
- const baseMerchant = {
701
- title: 'Merchant Interaction',
702
- narrative: 'A merchant approaches you.',
703
- choices: [
704
- { text: 'Trade goods', effect: { gold: 10 } },
705
- { text: 'Ask for information', effect: { reputation: 2 } }
706
- ],
707
- tags: ['merchant', 'economic']
708
- };
709
-
710
- const weatherMixin = {
711
- title: 'Weather Affected',
712
- narrative: 'The weather influences the situation.',
713
- choices: [
714
- { text: 'Adapt to weather conditions', effect: { reputation: 1 } },
715
- { text: 'Ignore the weather', effect: {} }
716
- ],
717
- tags: ['weather']
718
- };
719
-
720
- const conditionalAddon = {
721
- title: 'High-Level Merchant',
722
- narrative: 'This merchant deals in rare items.',
723
- choices: [
724
- { text: 'Purchase rare artifact', effect: { gold: -50 } },
725
- { text: 'Decline rare item', effect: {} }
726
- ],
727
- tags: ['rare', 'expensive']
728
- };
729
-
730
- // Register base templates
731
- generator.registerEventTemplate('base_merchant_demo', baseMerchant);
732
- generator.registerEventTemplate('weather_mixin_demo', weatherMixin);
733
- generator.registerEventTemplate('conditional_addon_demo', conditionalAddon);
734
-
735
- // Create advanced template with inheritance, mixins, and composition
736
- const advancedMerchant = {
737
- title: 'Advanced Merchant Encounter',
738
- narrative: 'A complex merchant situation unfolds with multiple factors.',
739
- choices: [
740
- { text: 'Execute perfect negotiation', effect: { gold: 25, reputation: 5 } },
741
- { text: 'Use merchant knowledge', effect: { reputation: 3 } }
742
- ],
743
- tags: ['advanced', 'complex'],
744
- extends: 'base_merchant_demo',
745
- mixins: ['weather_mixin_demo'],
746
- composition: [
747
- {
748
- template_id: 'conditional_addon_demo',
749
- merge_strategy: 'append',
750
- conditions: [{ type: 'stat_requirement', operator: 'gte', field: 'level', value: 10 }],
751
- priority: 1
752
- }
753
- ],
754
- conditional_choices: [
755
- {
756
- choice_index: 0,
757
- conditions: [{ type: 'stat_requirement', operator: 'gte', field: 'charisma', value: 15 }],
758
- show_when: true
759
- }
760
- ],
761
- dynamic_fields: [
762
- {
763
- field: 'narrative',
764
- conditions: [{ type: 'stat_requirement', operator: 'gte', field: 'gold', value: 1000 }],
765
- value_if_true: 'A wealthy merchant approaches, recognizing your affluence.',
766
- value_if_false: 'A merchant approaches, sizing up your modest means.'
767
- }
768
- ]
769
- };
770
-
771
- generator.registerEventTemplate('advanced_merchant_demo', advancedMerchant);
772
-
773
- // Test with low-level character (basic merchant only)
774
- console.log('Low-level character (Level 5, Charisma 10, Gold 100):');
775
- const basicEvent = safeExecute(() => generator.generateFromTemplate('advanced_merchant_demo', {
776
- level: 5, charisma: 10, gold: 100
777
- }), 'basic template generation');
778
-
779
- if (basicEvent) {
780
- printResult('Event type', basicEvent.type);
781
- printResult('Choices available', basicEvent.choices.length);
782
- printResult('Tags', basicEvent.tags.join(', '));
783
- }
784
-
785
- // Test with high-level character (full advanced merchant)
786
- console.log('\\nHigh-level character (Level 15, Charisma 20, Gold 2000):');
787
- const advancedEvent = safeExecute(() => generator.generateFromTemplate('advanced_merchant_demo', {
788
- level: 15, charisma: 20, gold: 2000
789
- }), 'advanced template generation');
790
-
791
- if (advancedEvent) {
792
- printResult('Event type', advancedEvent.type);
793
- printResult('Choices available', advancedEvent.choices.length);
794
- printResult('Tags', advancedEvent.tags.join(', '));
795
- printResult('Description shows wealth recognition', advancedEvent.description.includes('wealthy merchant'));
796
- }
797
-
798
- console.log('\\nAdvanced Template Features Demonstrated:');
799
- printResult('- Template Inheritance', '✅ Base merchant extended');
800
- printResult('- Mixin System', '✅ Weather behavior mixed in');
801
- printResult('- Conditional Composition', '✅ Rare items added for high-level players');
802
- printResult('- Dynamic Fields', '✅ Narrative adapts to player wealth');
803
- printResult('- Conditional Choices', '✅ Special options for high charisma');
804
- }
805
-
806
- function demoWorldBuilding() {
807
- printSection('🌍 Demo 20: World Building System (v2.0.0)');
808
-
809
- const generator = new RPGEventGenerator();
810
-
811
- console.log('Generating fantasy world...');
812
- const world = generator.generateWorld(42);
813
- printResult('World created successfully', `✅ ${world.regions.length} regions, ${world.factions.length} factions, ${world.events.length} historical events`);
814
-
815
- console.log('\nWorld Statistics:');
816
- printResult('- Regions created', world.regions.length);
817
- printResult('- Factions established', world.factions.length);
818
- printResult('- Historical events', world.events.length);
819
-
820
- console.log('\nSample Regions:');
821
- world.regions.slice(0, 3).forEach(region => {
822
- printResult(`- ${region.name}`, `${region.type} (${region.population.toLocaleString()} pop, stability: ${(region.political_stability * 100).toFixed(0)}%)`);
823
- });
824
-
825
- console.log('\nSample Factions:');
826
- world.factions.slice(0, 3).forEach(faction => {
827
- const allies = generator.getFactionAllies(faction.id).length;
828
- const enemies = generator.getFactionEnemies(faction.id).length;
829
- printResult(`- ${faction.name}`, `${faction.type} (influence: ${faction.influence.toFixed(1)}, allies: ${allies}, enemies: ${enemies})`);
830
- });
831
-
832
- console.log('\nFaction Power Rankings (Top 5):');
833
- const rankings = generator.getFactionPowerRanking();
834
- rankings.slice(0, 5).forEach((rank, i) => {
835
- printResult(`${i+1}. ${rank.name}`, `Power: ${rank.power.toFixed(1)}`);
836
- });
837
-
838
- console.log('\nHistorical Events:');
839
- world.events.forEach(event => {
840
- printResult(`- Year ${event.year}: ${event.title}`, `${event.type} (significance: ${event.significance.toFixed(1)})`);
841
- });
842
-
843
- console.log('\nSimulating 100 years of history...');
844
- const newEvents = generator.simulateWorldYears(100);
845
- printResult('New events generated', newEvents.length);
846
-
847
- console.log('\nRecent Historical Events:');
848
- newEvents.slice(-3).forEach(event => {
849
- printResult(`- Year ${event.year}: ${event.title}`, `${event.type} (significance: ${event.significance.toFixed(1)})`);
850
- });
851
-
852
- const finalStats = generator.getWorldStats();
853
- console.log('\nFinal World Statistics:');
854
- printResult('- Total regions', finalStats.totalRegions);
855
- printResult('- Total factions', finalStats.totalFactions);
856
- printResult('- Total historical events', finalStats.totalHistoricalEvents);
857
- printResult('- Average stability', (finalStats.averageStability * 100).toFixed(1) + '%');
858
- printResult('- Average prosperity', (finalStats.averageProsperity * 100).toFixed(1) + '%');
859
-
860
- console.log('\nWorld Building Features Demonstrated:');
861
- printResult('- Automated world generation', '✅ Regions, factions, and history created');
862
- printResult('- Faction relationship mapping', '✅ Diplomacy, allies, and enemies');
863
- printResult('- Historical event simulation', '✅ Dynamic world-changing events');
864
- printResult('- Power ranking system', '✅ Faction influence calculations');
865
- printResult('- Economic and political systems', '✅ Resources, stability, and prosperity');
866
- }
867
-
868
- function demoPerformanceOptimizations() {
869
- printSection('⚡ Demo 25: Performance Optimizations (v2.0.0)');
870
-
871
- const generator = new RPGEventGenerator();
872
-
873
- // Test template caching
874
- console.log('Testing Template Caching...');
875
- const template = {
876
- title: 'Performance Test Event',
877
- narrative: 'Testing caching performance.',
878
- choices: [
879
- { text: 'Choice 1', effect: { gold: 10 } },
880
- { text: 'Choice 2', effect: { gold: 20 } }
881
- ]
882
- };
883
-
884
- generator.registerEventTemplate('perf_test', template);
885
-
886
- // First generation (cache population)
887
- console.log('First generation run (populating cache)...');
888
- const start1 = Date.now();
889
- for (let i = 0; i < 10; i++) {
890
- generator.generateFromTemplate('perf_test', { level: 5 });
891
- }
892
- const end1 = Date.now();
893
- printResult('First run (10 events)', `${end1 - start1}ms`);
894
-
895
- // Second generation (cache utilization)
896
- console.log('Second generation run (using cache)...');
897
- const start2 = Date.now();
898
- for (let i = 0; i < 10; i++) {
899
- generator.generateFromTemplate('perf_test', { level: 5 });
900
- }
901
- const end2 = Date.now();
902
- printResult('Second run (10 events, cached)', `${end2 - start2}ms`);
903
-
904
- const cacheStats = generator.getTemplateCacheStats();
905
- console.log('\nCache Statistics:');
906
- printResult('- Processed templates cached', cacheStats.processedTemplates);
907
- printResult('- Generated events cached', cacheStats.generatedEvents);
908
-
909
- // Test batched generation
910
- console.log('\\nTesting Batched Generation...');
911
- const batchStart = Date.now();
912
- const batchedEvents = generator.generateEventsBatched(20, {}, 5);
913
- const batchEnd = Date.now();
914
- printResult('Batched generation (20 events)', `${batchEnd - batchStart}ms`);
915
- printResult('Generated events', batchedEvents.length);
916
-
917
- console.log('\\nPerformance Features Demonstrated:');
918
- printResult('- Template caching system', '✅ Repeated generations use cached results');
919
- printResult('- Event result caching', '✅ Identical contexts return cached events');
920
- printResult('- Batched generation', '✅ Efficient bulk event creation');
921
- printResult('- Cache statistics', '✅ Performance monitoring and optimization');
922
- }
923
-
924
- async function demoDatabaseIntegration() {
925
- printSection('💾 Demo 30: Database Integration (v2.0.0)');
926
-
927
- const generator = new RPGEventGenerator({ enableDatabase: true });
928
-
929
- // Give database a moment to initialize
930
- await new Promise(resolve => setTimeout(resolve, 10));
931
-
932
- const dbTemplate1 = {
933
- id: 'merchant_database_demo',
934
- title: 'Database Merchant',
935
- narrative: 'A merchant stored in the database system.',
936
- choices: [
937
- { text: 'Buy goods', effect: { gold: -50 } },
938
- { text: 'Sell goods', effect: { gold: 75 } },
939
- { text: 'Negotiate', effect: { gold: 25 } }
940
- ],
941
- tags: ['merchant', 'database', 'economy'],
942
- type: 'economic'
943
- };
944
-
945
- const dbTemplate2 = {
946
- id: 'combat_database_demo',
947
- title: 'Database Combat',
948
- narrative: 'A combat encounter from the database.',
949
- choices: [
950
- { text: 'Fight bravely', effect: { health: -20, experience: 50 } },
951
- { text: 'Try to flee', effect: { health: -5, reputation: -10 } },
952
- { text: 'Use strategy', effect: { experience: 30 } }
953
- ],
954
- tags: ['combat', 'database', 'adventure'],
955
- type: 'combat'
956
- };
957
-
958
- await safeExecute(async () => {
959
- // Store templates in database
960
- console.log('Storing templates in database...');
961
- await generator.storeTemplateInDatabase(dbTemplate1);
962
- await generator.storeTemplateInDatabase(dbTemplate2);
963
- console.log('Templates stored successfully');
964
-
965
- // Retrieve specific template
966
- const retrievedTemplate = await generator.getTemplateFromDatabase('merchant_database_demo');
967
- if (retrievedTemplate) {
968
- printResult('Retrieved template from database', retrievedTemplate.title);
969
- printResult('Template type', retrievedTemplate.type);
970
- printResult('Template tags', retrievedTemplate.tags.join(', '));
971
- }
972
-
973
- // Search templates by criteria
974
- console.log('\nSearching templates by type...');
975
- const economicTemplates = await generator.searchTemplatesInDatabase({ type: 'economic' });
976
- printResult('Found economic templates', economicTemplates.length);
977
-
978
- const combatTemplates = await generator.searchTemplatesInDatabase({ type: 'combat' });
979
- printResult('Found combat templates', combatTemplates.length);
980
-
981
- // Search by tags
982
- const merchantTemplates = await generator.getTemplatesByTags(['merchant']);
983
- printResult('Found merchant-tagged templates', merchantTemplates.length);
984
-
985
- // Get random templates
986
- const randomTemplates = await generator.getRandomTemplatesFromDatabase(3);
987
- printResult('Random templates retrieved', randomTemplates.length);
988
-
989
- // Get database statistics
990
- const dbStats = await generator.getDatabaseStats();
991
- console.log('\nDatabase Statistics:');
992
- printResult('- Total templates in database', dbStats.totalTemplates);
993
- printResult('- Templates with conditions', dbStats.templatesWithConditions);
994
- printResult('- Templates with composition', dbStats.templatesWithComposition);
995
- printResult('- Templates with inheritance', dbStats.templatesWithInheritance);
996
- printResult('- Average choices per template', dbStats.averageChoices.toFixed(1));
997
-
998
- console.log('\nDatabase Features Demonstrated:');
999
- printResult('- Template storage and retrieval', '✅ Templates persisted to database');
1000
- printResult('- Advanced search capabilities', '✅ Query by type, tags, and criteria');
1001
- printResult('- Random template selection', '✅ Efficient random sampling');
1002
- printResult('- Database statistics', '✅ Comprehensive analytics and reporting');
1003
- printResult('- Scalable architecture', '✅ Extensible adapter pattern for different databases');
1004
- });
1005
- }
1006
-
1007
- function demoEventEconomy() {
1008
- printSection('💰 Demo 29: Event Economy (v2.0.0)');
1009
-
1010
- safeExecute(() => {
1011
- // Import the EventEconomy class
1012
- const EventEconomy = require('./dist/scripts/event-economy');
1013
-
1014
- // Create economy instance
1015
- const economy = new EventEconomy('./user-content');
1016
-
1017
- // Create a sample theme
1018
- const sampleTheme = {
1019
- name: 'CyberWestern',
1020
- author: 'DemoCreator',
1021
- description: 'Cyberpunk western theme',
1022
- tags: ['cyberpunk', 'western', 'scifi'],
1023
- settings: {
1024
- theme: 'cyberpunk',
1025
- culture: 'western',
1026
- enableRuleEngine: true
1027
- },
1028
- trainingData: [
1029
- 'neon signs flicker in the dusty saloon',
1030
- 'robotic sheriffs maintain order',
1031
- 'cyborg outlaws ride mechanical horses'
1032
- ],
1033
- customRules: [],
1034
- statistics: {
1035
- trainingSentences: 3,
1036
- estimatedQuality: 75
1037
- }
1038
- };
1039
-
1040
- // Save the theme
1041
- const themePath = economy.saveTheme('CyberWestern', sampleTheme);
1042
- printResult('Theme saved to', themePath);
1043
-
1044
- // Load the theme
1045
- const loadedTheme = economy.loadTheme('CyberWestern');
1046
- printResult('Theme loaded', loadedTheme.name);
1047
- printResult('Author', loadedTheme.author);
1048
- printResult('Training sentences', loadedTheme.trainingData.length);
1049
-
1050
- // Show statistics
1051
- const stats = economy.getStatistics();
1052
- printResult('Total themes saved', stats.totalThemes);
1053
- printResult('Total quality score', Math.round(stats.averageThemeQuality) + '/100');
1054
-
1055
- }, 'event economy');
1056
- }
1057
-
1058
- runDemo().catch(console.error);
10
+ return require('./dist/index.js');
11
+ } catch {
12
+ console.error('Build required: npm run build && npm run demo');
13
+ process.exit(1);
14
+ }
15
+ }
16
+
17
+ function section(title) {
18
+ console.log(`\n--- ${title} ---`);
19
+ }
20
+
21
+ function printEvent(label, event) {
22
+ console.log(`${label}: ${event.title} (${event.type}, ${event.difficulty})`);
23
+ console.log(` ${event.description.slice(0, 120)}${event.description.length > 120 ? '...' : ''}`);
24
+ console.log(` Choices: ${event.choices.map(c => c.text).join(' | ')}`);
25
+ }
26
+
27
+ const { generateRPGEvent, RPGEventGenerator } = loadPackage();
28
+
29
+ console.log('RPG Event Generator — smoke demo');
30
+ console.log('Guides: npm run docs → docs/index.html');
31
+
32
+ section('1. One-liner (Tier 1)');
33
+ const quick = generateRPGEvent({
34
+ level: 10,
35
+ location: 'forest',
36
+ weather: 'rainy',
37
+ class: 'fighter',
38
+ timeOfDay: 'night'
39
+ });
40
+ printEvent('Event', quick);
41
+
42
+ section('2. Custom content (Tier 1)');
43
+ const generator = new RPGEventGenerator({ theme: 'fantasy', enableTemplates: false });
44
+ const EVENT_TYPES = [
45
+ 'ADVENTURE', 'COMBAT', 'ECONOMIC', 'EXPLORATION', 'GUILD', 'MAGIC', 'MYSTERY',
46
+ 'POLITICAL', 'QUEST', 'SOCIAL', 'SPELLCASTING', 'SUPERNATURAL', 'TECHNOLOGICAL', 'UNDERWORLD'
47
+ ];
48
+ const CUSTOM_TITLE = 'Smoke Test Event';
49
+ generator.addTrainingData({
50
+ titles: Object.fromEntries(EVENT_TYPES.map(t => [t, [CUSTOM_TITLE]])),
51
+ descriptions: Object.fromEntries(EVENT_TYPES.map(t => [t, ['Custom training data is active.']])),
52
+ choices: Object.fromEntries(EVENT_TYPES.map(t => [t, ['Attack', 'Defend', 'Yield']]))
53
+ }, 'default');
54
+
55
+ const custom = generator.generateEvent({ class: 'fighter' });
56
+ if (custom.title === CUSTOM_TITLE) {
57
+ printEvent('Custom content', custom);
58
+ } else {
59
+ console.log(`Unexpected title: ${custom.title} (expected ${CUSTOM_TITLE})`);
60
+ }
61
+
62
+ section('3. Weather modifiers (Tier 2)');
63
+ const rainy = generator.generateEvent({ weather: 'rainy', location: 'road' });
64
+ const mods = rainy.environmentalEffects?.appliedModifiers ?? [];
65
+ console.log(`Applied modifiers: ${mods.length ? mods.join(', ') : 'none'}`);
66
+ printEvent('Rainy event', rainy);
67
+
68
+ section('4. World lore (Tier 3)');
69
+ const world = generator.generateWorld(42);
70
+ const kingdom = world.regions.find(r => r.type === 'kingdom');
71
+ console.log(`World: ${world.regions.length} regions, ${world.factions.length} factions, ${world.events.length} historical events`);
72
+ if (kingdom) {
73
+ console.log(`Sample kingdom: ${kingdom.name}`);
74
+ const lore = generator.getWorldLore(kingdom.name);
75
+ if (lore) console.log(`Lore: ${lore.slice(0, 160)}${lore.length > 160 ? '...' : ''}`);
76
+ }
77
+
78
+ console.log('\nDone. Templates, DB, export scripts → see docs (Examples guide).');