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.
- package/README.md +48 -298
- package/demo.js +75 -1055
- package/dist/RPGEventGenerator.d.ts +24 -2
- package/dist/RPGEventGenerator.d.ts.map +1 -1
- package/dist/RPGEventGenerator.js +47 -21
- package/dist/RPGEventGenerator.js.map +1 -1
- package/dist/chains/ChainSystem.js +1 -1
- package/dist/chains/index.js +1 -1
- package/dist/core/ContextAnalyzer.js +1 -1
- package/dist/core/DifficultyScaler.js +1 -1
- package/dist/core/GeneratorCore.d.ts +19 -112
- package/dist/core/GeneratorCore.d.ts.map +1 -1
- package/dist/core/GeneratorCore.js +1817 -1437
- package/dist/core/GeneratorCore.js.map +1 -1
- package/dist/core/MarkovEngine.js +1 -1
- package/dist/core/index.js +1 -1
- package/dist/database/MemoryDatabaseAdapter.js +1 -1
- package/dist/database/TemplateDatabase.js +1 -1
- package/dist/environment/EnvironmentalSystem.d.ts +2 -0
- package/dist/environment/EnvironmentalSystem.d.ts.map +1 -1
- package/dist/environment/EnvironmentalSystem.js +46 -10
- package/dist/environment/EnvironmentalSystem.js.map +1 -1
- package/dist/environment/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/interfaces/systems.d.ts +1 -1
- package/dist/interfaces/systems.d.ts.map +1 -1
- package/dist/localization/LocalizationSystem.js +1 -1
- package/dist/localization/index.js +1 -1
- package/dist/relationships/RelationshipSystem.js +1 -1
- package/dist/relationships/index.js +1 -1
- package/dist/rules/RuleEngine.js +1 -1
- package/dist/rules/index.js +1 -1
- package/dist/src/types/world.d.ts +9 -0
- package/dist/src/types/world.d.ts.map +1 -1
- package/dist/templates/TemplateSystem.js +1 -1
- package/dist/templates/index.js +1 -1
- package/dist/time/TimeSystem.js +1 -1
- package/dist/time/index.js +1 -1
- package/dist/types/world.d.ts +9 -0
- package/dist/types/world.d.ts.map +1 -1
- package/dist/utils/array.js +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/file.js +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/random.js +1 -1
- package/dist/utils/text.js +1 -1
- package/dist/utils/validation.js +1 -1
- package/dist/utils/version.d.ts +8 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +11 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/world/WorldBuildingSystem.d.ts +16 -2
- package/dist/world/WorldBuildingSystem.d.ts.map +1 -1
- package/dist/world/WorldBuildingSystem.js +357 -155
- package/dist/world/WorldBuildingSystem.js.map +1 -1
- package/dist/world/index.d.ts +1 -1
- package/dist/world/index.d.ts.map +1 -1
- package/dist/world/index.js.map +1 -1
- package/dist/world/worldContent.d.ts +13 -0
- package/dist/world/worldContent.d.ts.map +1 -0
- package/dist/world/worldContent.js +109 -0
- package/dist/world/worldContent.js.map +1 -0
- 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
|
-
|
|
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
|
|
28
|
-
} catch
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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).');
|