rpg-event-generator 1.0.0 โ†’ 1.1.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 (3) hide show
  1. package/README.md +447 -256
  2. package/dist/index.js +1506 -47
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,32 +2,18 @@
2
2
 
3
3
  A powerful procedural event generation system for RPG games, capable of creating virtually infinite contextual events based on player state and game world.
4
4
 
5
- ## โœจ Features
6
-
7
- - **Infinite Event Generation**: Creates unique, contextual events using custom Markov chains and procedural techniques
8
- - **Player-Aware**: Events adapt to player stats, career, relationships, life stage, reputation, and social standing
9
- - **14+ Dramatic Event Types**: From court scandals and noble duels to ancient curses and bandit kings
10
- - **Immersive Storytelling**: Each event features rich narratives with atmospheric descriptions and meaningful consequences
11
- - **Dynamic Effects**: Context-aware rewards and consequences that scale with character development and power level
12
- - **Career Integration**: Events specifically tailored to noble, merchant, warrior, and criminal careers
13
- - **Relationship Impact**: Events that affect and are affected by your social connections and personal history
14
- - **Seasonal & Location Themes**: Events adapt to time of year and geographical setting for added immersion
15
- - **Consequence Tracking**: Events can have long-term effects on character development and reputation
16
- - **Personality-Driven Choices**: Multiple meaningful choices that define your character's personality and path
17
- - **Quality Filtering**: Built-in filters ensure only interesting, non-generic events are generated
18
- - **Modular Design**: Easy to integrate into existing game systems
19
- - **Highly Configurable**: Customize training data, templates, and generation parameters
20
-
21
- ## ๐Ÿš€ Quick Start
5
+ ## ๐Ÿš€ Installation
22
6
 
23
7
  ```bash
24
8
  npm install rpg-event-generator
25
9
  ```
26
10
 
11
+ ## โœจ Quick Start
12
+
27
13
  ```javascript
28
14
  import { RPGEventGenerator, generateRPGEvent } from 'rpg-event-generator';
29
15
 
30
- // Quick single event
16
+ // Simple event generation
31
17
  const event = generateRPGEvent({
32
18
  age: 25,
33
19
  gold: 500,
@@ -35,65 +21,44 @@ const event = generateRPGEvent({
35
21
  career: 'merchant'
36
22
  });
37
23
 
38
- console.log(event.title); // "Golden Opportunity"
39
- console.log(event.description); // Procedurally generated description
40
- console.log(event.choices); // Array of choices with effects
24
+ console.log(event.title); // "Golden Opportunity"
25
+ console.log(event.description); // Procedurally generated narrative
26
+ console.log(event.choices); // Array of meaningful choices
27
+ ```
41
28
 
42
- // Advanced usage with custom generator
43
- const generator = new RPGEventGenerator({
44
- stateSize: 2,
45
- trainingData: ['Your custom story fragments...']
46
- });
29
+ ## ๐Ÿ“‹ Features
47
30
 
48
- // Generate multiple events
49
- const events = generator.generateEvents({
50
- age: 30,
51
- gold: 1000,
52
- influence: 25,
53
- career: 'knight',
54
- skills: { combat: 60, diplomacy: 40 }
55
- }, 3);
56
- ```
31
+ - **๐ŸŽฒ Infinite Event Generation**: Custom Markov chains create unique, contextual events
32
+ - **๐Ÿ‘ค Player-Aware**: Events adapt to stats, career, relationships, reputation, and social standing
33
+ - **๐ŸŽญ 14+ Event Types**: Court scandals, noble duels, ancient curses, bandit kings, and more
34
+ - **๐Ÿ“– Immersive Storytelling**: Rich narratives with atmospheric descriptions and meaningful consequences
35
+ - **โš–๏ธ Dynamic Difficulty Scaling**: Events automatically scale based on player power level
36
+ - **๐ŸŽจ Thematic Training Sets**: Fantasy, sci-fi, and historical themes with cultural variants
37
+ - **โ›“๏ธ Event Chains**: Multi-part story sequences with escalating consequences
38
+ - **โฐ Time-Based Events**: Seasonal changes and evolving long-term storylines
39
+ - **๐Ÿ”ง Modular Event System**: Create and manage custom templates, training data, and chains
40
+ - **๐Ÿ’พ Game Integration**: Proper save/load state management for real games
41
+ - **๐Ÿงช Comprehensive Testing**: 45+ automated tests ensuring reliability
57
42
 
58
- ## ๐Ÿ“– Usage Examples
43
+ ## ๐Ÿ“– Usage Guide
59
44
 
60
45
  ### Basic Event Generation
61
46
 
62
47
  ```javascript
63
48
  const generator = new RPGEventGenerator();
64
-
65
- // Generate a random event
66
49
  const event = generator.generateEvent();
67
50
 
68
51
  console.log(event);
69
52
  // {
70
53
  // id: "event_1704567890123_xyz789",
71
54
  // title: "Perilous Bandit King's Challenge",
72
- // description: "The infamous bandit king blocks your path, offering you a choice: join his band or face certain death. Your business interests are directly affected by this development. Choose wisely, for the wrong path leads to ruin.",
73
- // narrative: "The infamous bandit king blocks your path, offering you a choice: join his band or face certain death.",
55
+ // description: "Generated narrative based on Markov chains...",
74
56
  // choices: [
75
- // {
76
- // text: "Join the bandits",
77
- // effect: { gold: 375, reputation: -23, combat_skill: 12 },
78
- // consequence: "bandit"
79
- // },
80
- // {
81
- // text: "Challenge him to single combat",
82
- // effect: { reputation: 32, health: -18 },
83
- // requirements: { combat_skill: 60 },
84
- // consequence: "hero"
85
- // },
86
- // {
87
- // text: "Bribe your way past",
88
- // effect: { gold: -320, safe_passage: true },
89
- // consequence: "diplomat"
90
- // }
57
+ // { text: "Fight back", effect: { health: -20, reputation: 25 } },
58
+ // { text: "Pay tribute", effect: { gold: -200, safe_passage: true } }
91
59
  // ],
92
60
  // type: "BANDIT_KING",
93
- // consequence: null,
94
- // urgency: "normal",
95
- // theme: "adventure",
96
- // context: { /* player context used */ }
61
+ // difficulty: "normal"
97
62
  // }
98
63
  ```
99
64
 
@@ -106,121 +71,355 @@ const playerContext = {
106
71
  influence: 40,
107
72
  reputation: 25,
108
73
  career: 'noble',
109
- skills: {
110
- diplomacy: 70,
111
- combat: 45,
112
- intrigue: 30
113
- },
74
+ skills: { diplomacy: 70, combat: 45, intrigue: 30 },
114
75
  relationships: [
115
- { name: 'Lord Harrington', type: 'ally', relationship: 60 },
116
- { name: 'Lady Beaumont', type: 'lover', relationship: 45 }
76
+ { name: 'Lord Harrington', type: 'ally', relationship: 60 }
117
77
  ],
118
78
  location: 'capital',
119
79
  season: 'winter'
120
80
  };
121
81
 
122
82
  const event = generator.generateEvent(playerContext);
123
- // Generates events like:
124
- // - Diplomatic missions (high diplomacy skill)
125
- // - Court intrigue opportunities (high influence)
126
- // - Social events involving relationships
127
- // - Winter-themed challenges
83
+ // Generates events appropriate to noble career, high influence, winter season
128
84
  ```
129
85
 
130
86
  ### Custom Training Data
131
87
 
88
+ Enhance text generation with your own story fragments:
89
+
132
90
  ```javascript
133
91
  const customTrainingData = [
134
92
  'In the shadowed alleys of the ancient city',
135
- 'The dragon\'s roar echoes through the mountains',
136
- 'Elven merchants display their enchanted wares',
137
- 'A dwarven smith forges weapons of legend',
138
- 'The tavern is filled with adventurers and mercenaries',
139
- 'Ancient runes glow with mystical power',
140
- 'The forest whispers secrets to those who listen'
93
+ 'The dragon\'s roar echoes through the misty mountains',
94
+ 'Elven merchants display their enchanted crystal wares',
95
+ 'A dwarven smith forges weapons of legendary power',
96
+ 'The tavern overflows with adventurers and mysterious strangers',
97
+ 'Ancient runes glow with ethereal magical energy',
98
+ 'The enchanted forest whispers secrets to those who listen carefully'
141
99
  ];
142
100
 
143
101
  const generator = new RPGEventGenerator({
144
102
  trainingData: customTrainingData
145
103
  });
104
+
105
+ // Events will now incorporate your custom story elements
106
+ const event = generator.generateEvent();
107
+ // May generate: "In the shadowed alleys of the ancient city, a mysterious stranger approaches..."
146
108
  ```
147
109
 
148
- ## ๐Ÿ”ง API Reference
110
+ ### Thematic Training Sets
111
+
112
+ ```javascript
113
+ // Fantasy (default) - knights, magic, dragons
114
+ const fantasyGen = new RPGEventGenerator({ theme: 'fantasy' });
115
+
116
+ // Fantasy with Norse culture - vikings, runes, fjords
117
+ const norseGen = new RPGEventGenerator({
118
+ theme: 'fantasy',
119
+ culture: 'norse'
120
+ });
121
+ const norseEvent = norseGen.generateEvent();
122
+ // Generates: "The longships sail into the fjord under the northern lights..."
123
+
124
+ // Sci-fi - corporations, AI, space exploration
125
+ const sciFiGen = new RPGEventGenerator({ theme: 'sci-fi' });
126
+
127
+ // Cyberpunk sci-fi - neon cities, megacorps, hackers
128
+ const cyberpunkGen = new RPGEventGenerator({
129
+ theme: 'sci-fi',
130
+ culture: 'cyberpunk'
131
+ });
132
+ const cyberEvent = cyberpunkGen.generateEvent();
133
+ // Generates: "Neon lights reflect off rain-slicked streets in the megacity sprawl..."
134
+
135
+ // Historical - medieval politics, exploration, warfare
136
+ const historicalGen = new RPGEventGenerator({ theme: 'historical' });
137
+
138
+ // Victorian historical - industrial revolution, social reform
139
+ const victorianGen = new RPGEventGenerator({
140
+ theme: 'historical',
141
+ culture: 'victorian'
142
+ });
143
+ const victorianEvent = victorianGen.generateEvent();
144
+ // Generates: "Steam engines power the industrial revolution across soot-stained cities..."
145
+ ```
146
+
147
+ ### Event Chains
148
+
149
+ ```javascript
150
+ // Start a multi-part storyline
151
+ const generator = new RPGEventGenerator();
152
+ const firstEvent = generator.startChain('BANDIT_RISING');
153
+
154
+ console.log(firstEvent.title); // "Treacherous Bandit Ambush"
155
+ console.log(firstEvent.chainId); // "chain_1704567890123_xyz789"
156
+
157
+ // Advance chain based on player choice
158
+ const nextEvent = generator.advanceChain(firstEvent.chainId, 'hero');
159
+ console.log(nextEvent.title); // "Perilous Bandit King's Challenge"
160
+
161
+ // Check active chains
162
+ const activeChains = generator.getActiveChains();
163
+ console.log(`Active chains: ${activeChains.length}`);
164
+
165
+ // Available built-in chains:
166
+ // - BANDIT_RISING: Highway robbery escalating to kingdom threat
167
+ // - COURT_SCANDAL_CHAIN: Royal intrigue with multiple betrayals
168
+ // - CURSE_OF_THE_ARTIFACT: Ancient curse with escalating effects
169
+ // - MERCHANT_EMPIRE: Trade empire building with setbacks
170
+ ```
149
171
 
150
- ### RPGEventGenerator Class
172
+ ### Time-Based Events
151
173
 
152
- #### Constructor Options
174
+ ```javascript
175
+ // Advance game time and handle due events
176
+ const dueEvents = generator.advanceGameDay();
177
+
178
+ dueEvents.forEach(event => {
179
+ if (event.type === 'time_based_chain') {
180
+ const chainData = generator.timeSystem.timeBasedEvents.get(event.chainId);
181
+ const gameEvent = generator.generateChainEvent(chainData);
182
+ // Add to your game's event system
183
+ }
184
+ });
185
+
186
+ // Start evolving storylines
187
+ generator.startTimeBasedChain('POLITICAL_UPRISING');
188
+ // - Day 1: Whispers of dissent appear
189
+ // - Day 7: Public protests erupt
190
+ // - Day 14: Open rebellion begins
191
+ // - Day 21: Revolutionary climax
192
+
193
+ // Check current game time
194
+ const currentTime = generator.getCurrentTime();
195
+ console.log(`Day ${currentTime.day}, Season: ${currentTime.season}`);
196
+ ```
197
+
198
+ ### Modular Event System
199
+
200
+ ```javascript
201
+ // Register custom event templates
202
+ const customTemplate = {
203
+ title: 'Mystic Vision',
204
+ narrative: 'You experience a vivid prophetic dream showing future events.',
205
+ choices: [
206
+ {
207
+ text: 'Seek out the prophecy',
208
+ effect: { wisdom: 15, risk: 20 },
209
+ consequence: 'visionary'
210
+ },
211
+ {
212
+ text: 'Dismiss it as a dream',
213
+ effect: { stress: -10 },
214
+ consequence: 'skeptical'
215
+ }
216
+ ]
217
+ };
218
+
219
+ generator.registerEventTemplate('MYSTIC_VISION', customTemplate);
220
+
221
+ // Add custom training data for better text generation
222
+ generator.addCustomTrainingData([
223
+ 'The ancient prophecy foretells of great change',
224
+ 'Mystic visions reveal hidden truths to the worthy',
225
+ 'Dreams of the future guide the destinies of heroes'
226
+ ], 'mystical');
227
+
228
+ // Create custom event chains
229
+ const visionChain = {
230
+ name: 'Prophetic Journey',
231
+ description: 'A chain of events triggered by mystic visions',
232
+ stages: [
233
+ { day: 1, template: 'MYSTIC_VISION' },
234
+ { day: 5, template: 'ANCIENT_RUINS' },
235
+ { day: 10, template: 'FINAL_PROPHECY' }
236
+ ]
237
+ };
238
+
239
+ generator.registerEventChain('PROPHECY_CHAIN', visionChain);
240
+
241
+ // Export/import custom content for sharing
242
+ const customContent = generator.exportCustomContent();
243
+ console.log('Exported:', Object.keys(customContent.templates).length, 'templates');
244
+
245
+ const newGenerator = new RPGEventGenerator();
246
+ const importResult = newGenerator.importCustomContent(customContent);
247
+ console.log('Imported:', importResult.templates.success, 'templates');
248
+ ```
249
+
250
+ ### Dynamic Difficulty Scaling
251
+
252
+ Events automatically scale based on player power level:
253
+
254
+ ```javascript
255
+ // Weak character (easy difficulty)
256
+ const weakling = {
257
+ gold: 50,
258
+ influence: 10,
259
+ skills: { combat: 20 }
260
+ };
261
+ const easyEvent = generator.generateEvent(weakling);
262
+ console.log(`Difficulty: ${easyEvent.difficulty}`); // "easy"
263
+ // Effects scaled for beginners: higher rewards, lower penalties
264
+
265
+ // Powerful character (hard difficulty)
266
+ const hero = {
267
+ gold: 50000,
268
+ influence: 500,
269
+ skills: { combat: 100, diplomacy: 80 },
270
+ relationships: [{ name: 'King', type: 'ally', relationship: 80 }]
271
+ };
272
+ const hardEvent = generator.generateEvent(hero);
273
+ console.log(`Difficulty: ${hardEvent.difficulty}`); // "hard"
274
+ // Effects scaled for challenge: lower rewards, higher penalties
275
+
276
+ // Legendary character (legendary difficulty)
277
+ const godlike = {
278
+ gold: 200000,
279
+ influence: 1000,
280
+ skills: { combat: 200, diplomacy: 150 },
281
+ age: 120,
282
+ reputation: 95
283
+ };
284
+ const epicEvent = generator.generateEvent(godlike);
285
+ console.log(`Difficulty: ${epicEvent.difficulty}`); // "legendary"
286
+ // Effects scaled for epic gameplay: minimal rewards, maximum penalties
287
+ ```
288
+
289
+ **Difficulty Tiers:**
290
+ - **Easy** (Power 0-50): Generous rewards, forgiving penalties
291
+ - **Normal** (Power 25-150): Standard scaling, balanced challenges
292
+ - **Hard** (Power 100-300): Reduced rewards, harsher penalties
293
+ - **Legendary** (Power 250+): Minimal rewards, extreme challenges
294
+
295
+ ## ๐Ÿ”ง API Reference
296
+
297
+ ### Constructor Options
153
298
 
154
299
  ```javascript
155
300
  const generator = new RPGEventGenerator({
156
- stateSize: 2, // Markov chain state size (default: 2)
157
- trainingData: [...] // Custom training data array (optional)
301
+ stateSize: 2, // Markov chain state size (default: 2)
302
+ trainingData: [...], // Custom training data array
303
+ theme: 'fantasy', // 'fantasy', 'sci-fi', 'historical'
304
+ culture: 'norse' // Cultural variant within theme
158
305
  });
159
306
  ```
160
307
 
161
- #### Methods
308
+ ### Core Methods
162
309
 
163
- - `generateEvent(playerContext)` - Generate a single event
310
+ - `generateEvent(playerContext)` - Generate single event
164
311
  - `generateEvents(playerContext, count)` - Generate multiple events
165
- - `addTrainingData(data)` - Add more training data
166
- - `resetTrainingData(data)` - Reset with new training data
312
+ - `generateTimeAwareEvent(playerContext)` - Generate season-aware event
313
+
314
+ ### Event Chain Methods
315
+
316
+ - `startChain(chainId)` - Start choice-based event chain
317
+ - `advanceChain(chainId, choice)` - Advance chain based on choice
318
+ - `getActiveChains()` - Get all active chains
319
+
320
+ ### Time-Based Methods
321
+
322
+ - `advanceGameDay()` - Advance time and return due events
323
+ - `startTimeBasedChain(chainId)` - Start time-evolving chain
324
+ - `getCurrentTime()` - Get current game time/season
325
+ - `getActiveTimeChains()` - Get active time-based chains
326
+
327
+ ### Game State Methods
328
+
329
+ - `getGameState()` - Export complete game state
330
+ - `loadGameState(state)` - Import saved game state
331
+
332
+ ### Modular Methods
333
+
334
+ - `registerEventTemplate(id, template)` - Add custom event template
335
+ - `addCustomTrainingData(data, category)` - Add custom training data
336
+ - `registerEventChain(id, chainConfig)` - Add custom event chain
337
+ - `exportCustomContent()` - Export custom templates/chains/data
338
+ - `importCustomContent(content)` - Import custom content
167
339
 
168
340
  ### Player Context Object
169
341
 
170
342
  ```javascript
171
343
  {
172
- age: number, // Player age
173
- gold: number, // Player wealth
174
- influence: number, // Political/social influence
175
- reputation: number, // Social reputation
176
- career: string, // Player's career/job
177
- skills: { // Skill levels object
178
- combat: number,
344
+ age: number, // Player age
345
+ gold: number, // Player wealth
346
+ influence: number, // Political/social influence
347
+ reputation: number, // Social reputation
348
+ career: string, // Player's career/job ('noble', 'merchant', 'warrior', etc.)
349
+ skills: { // Skill levels object
350
+ combat: number, // 0-100 scale
179
351
  diplomacy: number,
180
- // ... other skills
352
+ intrigue: number,
353
+ magic: number,
354
+ survival: number
181
355
  },
182
- relationships: [{ // Array of relationships
183
- name: string,
184
- type: string, // 'friend', 'lover', 'ally', etc.
185
- relationship: number // Relationship strength (0-100)
356
+ relationships: [{ // Array of NPC relationships
357
+ name: string, // NPC name
358
+ type: string, // 'friend', 'lover', 'ally', 'enemy', 'rival'
359
+ relationship: number // Relationship strength (0-100)
186
360
  }],
187
- location: string, // Current location
188
- season: string // Current season
361
+ location: string, // Current location ('capital', 'village', 'forest', etc.)
362
+ season: string // Current season ('spring', 'summer', 'autumn', 'winter')
189
363
  }
190
364
  ```
191
365
 
192
- ### Event Object Structure
366
+ ### Complete Event Object Structure
193
367
 
194
368
  ```javascript
195
369
  {
196
- id: string, // Unique event identifier
197
- title: string, // Dynamic, context-aware title
198
- description: string, // Rich procedural description
199
- narrative: string, // Core story premise
200
- choices: [{ // Array of meaningful choices
201
- text: string, // Choice text with contextual flavor
202
- effect: { // Effects scaled by context
203
- gold?: number, // Wealth changes
204
- influence?: number, // Social/political power
205
- reputation?: number, // Social standing
206
- health?: number, // Physical well-being
207
- stress?: number, // Mental strain
208
- karma?: number, // Moral standing
209
- // ... many more effects
370
+ id: "event_1704567890123_xyz789", // Unique event identifier
371
+ title: "Perilous Bandit King's Challenge", // Dynamic, context-aware title
372
+ description: "The infamous bandit king blocks your path, offering you a choice...", // Rich procedural description
373
+ narrative: "The infamous bandit king blocks your path, offering you a choice: join his band or face certain death.",
374
+ choices: [
375
+ {
376
+ text: "Join the bandits",
377
+ effect: { gold: 375, reputation: -23, combat_skill: 12 },
378
+ consequence: "bandit"
210
379
  },
211
- consequence: string // Long-term character effect
212
- }],
213
- type: string, // Rich event category (COURT_SCANDAL, etc.)
214
- consequence: string|null, // Applied consequence after choice
215
- urgency: string, // 'normal', 'high', 'critical'
216
- theme: string, // 'political', 'criminal', 'supernatural', etc.
217
- context: object // Full context used for generation
380
+ {
381
+ text: "Challenge him to single combat",
382
+ effect: { reputation: 32, health: -18 },
383
+ requirements: { combat_skill: 60 },
384
+ consequence: "hero"
385
+ },
386
+ {
387
+ text: "Bribe your way past",
388
+ effect: { gold: -320, safe_passage: true },
389
+ consequence: "diplomat"
390
+ }
391
+ ],
392
+ type: "BANDIT_KING",
393
+ consequence: null,
394
+ context: { /* Full context used for generation */ },
395
+ urgency: "normal",
396
+ theme: "adventure",
397
+ difficulty: "normal"
218
398
  }
219
399
  ```
220
400
 
221
- ## ๐ŸŽฎ Integration Guide
401
+ ## ๐ŸŽฎ Game Integration
402
+
403
+ ### Real-Time Strategy Integration
404
+
405
+ ```javascript
406
+ function onNewGameDay() {
407
+ const dueEvents = generator.advanceGameDay();
408
+
409
+ dueEvents.forEach(event => {
410
+ if (event.type === 'time_based_chain') {
411
+ const chainData = generator.timeSystem.timeBasedEvents.get(event.chainId);
412
+ const gameEvent = generator.generateChainEvent(chainData);
413
+ triggerInGameEvent(gameEvent);
414
+ } else if (event.type === 'seasonal_random') {
415
+ const seasonalEvent = generator.generateTimeAwareEvent(playerContext);
416
+ triggerInGameEvent(seasonalEvent);
417
+ }
418
+ });
419
+ }
420
+ ```
222
421
 
223
- ### React Native Game Integration
422
+ ### React Game Integration
224
423
 
225
424
  ```javascript
226
425
  import React, { useState, useEffect } from 'react';
@@ -243,13 +442,24 @@ function GameEventSystem({ playerStats }) {
243
442
  setCurrentEvent(null); // Clear event
244
443
  };
245
444
 
246
- if (!currentEvent) return null;
445
+ if (!currentEvent) return <div>No active events</div>;
247
446
 
248
447
  return (
249
- <EventDialog
250
- event={currentEvent}
251
- onChoice={handleChoice}
252
- />
448
+ <div className="event-dialog">
449
+ <h2>{currentEvent.title}</h2>
450
+ <p>{currentEvent.description}</p>
451
+ <div className="choices">
452
+ {currentEvent.choices.map((choice, index) => (
453
+ <button
454
+ key={index}
455
+ onClick={() => handleChoice(index)}
456
+ className="choice-button"
457
+ >
458
+ {choice.text}
459
+ </button>
460
+ ))}
461
+ </div>
462
+ </div>
253
463
  );
254
464
  }
255
465
  ```
@@ -257,174 +467,155 @@ function GameEventSystem({ playerStats }) {
257
467
  ### Redux Integration
258
468
 
259
469
  ```javascript
260
- // Action creators
261
- export const generateEvent = (playerContext) => {
262
- const generator = new RPGEventGenerator();
263
- const event = generator.generateEvent(playerContext);
264
-
265
- return {
266
- type: 'GENERATE_EVENT',
267
- payload: event
268
- };
269
- };
470
+ // Action Types
471
+ export const GENERATE_EVENT = 'GENERATE_EVENT';
472
+ export const RESOLVE_EVENT = 'RESOLVE_EVENT';
473
+ export const ADVANCE_GAME_DAY = 'ADVANCE_GAME_DAY';
474
+
475
+ // Action Creators
476
+ export const generateEvent = (playerContext) => ({
477
+ type: GENERATE_EVENT,
478
+ payload: { playerContext }
479
+ });
270
480
 
271
481
  export const resolveEvent = (eventId, choiceIndex) => ({
272
- type: 'RESOLVE_EVENT',
482
+ type: RESOLVE_EVENT,
273
483
  payload: { eventId, choiceIndex }
274
484
  });
275
485
 
486
+ export const advanceGameDay = () => ({
487
+ type: ADVANCE_GAME_DAY
488
+ });
489
+
276
490
  // Reducer
277
- const eventReducer = (state = {}, action) => {
491
+ const initialState = {
492
+ generator: new RPGEventGenerator(),
493
+ currentEvent: null,
494
+ gameTime: { day: 1, season: 'spring' }
495
+ };
496
+
497
+ const eventReducer = (state = initialState, action) => {
278
498
  switch (action.type) {
279
- case 'GENERATE_EVENT':
280
- return { ...state, currentEvent: action.payload };
281
- case 'RESOLVE_EVENT':
282
- return { ...state, currentEvent: null };
499
+ case GENERATE_EVENT:
500
+ const event = state.generator.generateEvent(action.payload.playerContext);
501
+ return { ...state, currentEvent: event };
502
+
503
+ case RESOLVE_EVENT:
504
+ // Apply choice effects to player state
505
+ const choice = state.currentEvent.choices[action.payload.choiceIndex];
506
+ const newPlayerState = applyChoiceEffects(choice.effect);
507
+ return {
508
+ ...state,
509
+ currentEvent: null,
510
+ playerState: newPlayerState
511
+ };
512
+
513
+ case ADVANCE_GAME_DAY:
514
+ const dueEvents = state.generator.advanceGameDay();
515
+ return {
516
+ ...state,
517
+ gameTime: state.generator.getCurrentTime(),
518
+ dueEvents: dueEvents
519
+ };
520
+
283
521
  default:
284
522
  return state;
285
523
  }
286
524
  };
287
525
  ```
288
526
 
289
- ## ๐Ÿงช Testing
527
+ ### Save/Load System
290
528
 
291
- ```bash
292
- npm test
293
- ```
294
-
295
- The package includes comprehensive tests covering:
296
- - Event generation with various contexts
297
- - Effect resolution
298
- - Markov chain text generation
299
- - Template selection algorithms
300
-
301
- ## ๐ŸŽฏ Event Types
302
-
303
- ### Court & Political (Variable probability)
304
- - **Court Scandal**: Royal court intrigue with betrayal and scandal
305
- - **Noble Duel**: Honor challenges and duels of reputation
306
- - **Market Crash**: Economic disasters affecting trade and wealth
307
- - **Trade War**: Merchant rivalries and economic warfare
308
-
309
- ### Criminal Underworld (Variable probability)
310
- - **Thieves' Guild**: Criminal organization recruitment and underworld dealings
311
- - **Blackmail Opportunity**: Leverage compromising information for gain
312
- - **Bandit King Challenge**: Highway robbery and outlaw confrontations
313
-
314
- ### Supernatural & Mysterious (Variable probability)
315
- - **Ancient Curse**: Cursed artifacts and supernatural afflictions
316
- - **Ghostly Visitation**: Spirits seeking justice or redemption
317
- - **Lost Civilization**: Archaeological discoveries and ancient treasures
318
-
319
- ### Personal & Dramatic (Variable probability)
320
- - **Forbidden Love**: Romance across social boundaries with scandal
321
- - **Family Secret**: Hidden lineage and ancestral revelations
322
- - **Desertion Temptation**: Military crises testing loyalty and courage
323
- - **Mercenary Contract**: Dangerous employment with high rewards
324
-
325
- ### Adventure & Exploration (Variable probability)
326
- - **Bandit King**: Confrontations with notorious outlaws
327
- - **Lost Civilization**: Exploration of ancient ruins and artifacts
328
-
329
- Probabilities dynamically adjust based on player career, skills, reputation, wealth, and current life circumstances.
330
-
331
- ## ๐Ÿ”„ How It Works
332
-
333
- ### 1. Context Analysis
334
- The generator analyzes player stats to understand their current situation and capabilities.
335
-
336
- ### 2. Template Selection
337
- Based on context, it selects an appropriate event template from 14+ rich narrative types (Court Scandal, Forbidden Love, Ancient Curse, etc.).
338
-
339
- ### 3. Procedural Description
340
- Uses custom Markov chains trained on immersive RPG-themed text to generate unique, atmospheric descriptions.
341
-
342
- ### 4. Dynamic Choices
343
- Creates contextually appropriate choices with effects that scale based on player stats, career, and relationships.
529
+ ```javascript
530
+ // Save complete game state
531
+ function saveGame(playerState) {
532
+ const gameState = {
533
+ player: playerState,
534
+ events: generator.getGameState(),
535
+ timestamp: Date.now()
536
+ };
344
537
 
345
- ### 5. Effect Resolution
346
- Converts effect ranges into specific numbers and applies sophisticated context multipliers based on character background.
538
+ localStorage.setItem('rpgGameSave', JSON.stringify(gameState));
539
+ console.log('Game saved successfully');
540
+ }
347
541
 
348
- ## ๐ŸŽจ Customization
542
+ // Load complete game state
543
+ function loadGame() {
544
+ try {
545
+ const savedGame = JSON.parse(localStorage.getItem('rpgGameSave'));
546
+ if (!savedGame) return false;
349
547
 
350
- ### Custom Event Templates
548
+ // Restore generator state
549
+ generator.loadGameState(savedGame.events);
351
550
 
352
- ```javascript
353
- const customTemplates = {
354
- QUEST: {
355
- title: 'Epic Quest',
356
- choices: [
357
- { text: 'Accept the quest', effect: { influence: [20, 40] } },
358
- { text: 'Decline politely', effect: {} }
359
- ]
360
- }
361
- };
551
+ // Restore player state
552
+ return savedGame.player;
362
553
 
363
- // Extend the generator
364
- class CustomRPGEventGenerator extends RPGEventGenerator {
365
- constructor(options) {
366
- super(options);
367
- this.templates = { ...this.templates, ...customTemplates };
554
+ } catch (error) {
555
+ console.error('Failed to load game:', error);
556
+ return false;
368
557
  }
369
558
  }
370
559
  ```
371
560
 
372
- ### Custom Effect Types
561
+ ## ๐Ÿงช Testing
373
562
 
374
- ```javascript
375
- // Add custom effects
376
- const event = generator.generateEvent(playerContext);
563
+ ```bash
564
+ npm test
565
+ ```
377
566
 
378
- // Custom effect resolution
379
- function resolveCustomEffects(choice, playerContext) {
380
- const effects = resolveEffect(choice.effect, playerContext);
567
+ **Comprehensive test coverage (45+ tests):**
568
+ - โœ… Core event generation and validation
569
+ - โœ… Context adaptation and player responsiveness
570
+ - โœ… Thematic systems and cultural variants
571
+ - โœ… Event chains and multi-stage progression
572
+ - โœ… Dynamic difficulty scaling
573
+ - โœ… Time systems and seasonal mechanics
574
+ - โœ… Modular features and custom content
575
+ - โœ… Edge cases and error handling
576
+ - โœ… Game state persistence and integration
381
577
 
382
- // Add custom logic
383
- if (effects.experience) {
384
- // Handle experience gain
385
- }
578
+ ## ๐ŸŽฏ Event Types
386
579
 
387
- if (effects.relationshipChange) {
388
- // Update relationship values
389
- }
580
+ ### Court & Political
581
+ - **Court Scandal**: Royal intrigue with betrayal and scandal
582
+ - **Noble Duel**: Honour challenges and duels of reputation
583
+ - **Market Crash**: Economic disasters affecting trade
584
+ - **Trade War**: Merchant rivalries and economic warfare
390
585
 
391
- return effects;
392
- }
393
- ```
586
+ ### Criminal Underworld
587
+ - **Thieves' Guild**: Criminal organisation recruitment
588
+ - **Blackmail Opportunity**: Leverage compromising information
589
+ - **Bandit King Challenge**: Highway robbery confrontations
394
590
 
395
- ## ๐Ÿ“Š Performance
591
+ ### Supernatural & Mysterious
592
+ - **Ancient Curse**: Cursed artefacts and afflictions
593
+ - **Ghostly Visitation**: Spirits seeking justice
594
+ - **Lost Civilisation**: Archaeological discoveries
396
595
 
397
- - **Generation Speed**: ~10-50ms per event
398
- - **Memory Usage**: ~2-5MB for trained Markov generator
399
- - **Infinite Variety**: Can generate millions of unique events
400
- - **Scalable**: Works with any number of players/contexts
596
+ ### Personal & Dramatic
597
+ - **Forbidden Love**: Romance across social boundaries
598
+ - **Family Secret**: Hidden lineage revelations
599
+ - **Desertion Temptation**: Military loyalty crises
600
+ - **Mercenary Contract**: Dangerous employment opportunities
401
601
 
402
602
  ## ๐Ÿค Contributing
403
603
 
404
604
  1. Fork the repository
405
- 2. Create a feature branch
406
- 3. Add tests for new functionality
407
- 4. Ensure all tests pass
408
- 5. Submit a pull request
605
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
606
+ 3. Commit changes (`git commit -m 'Add amazing feature'`)
607
+ 4. Push to branch (`git push origin feature/amazing-feature`)
608
+ 5. Open a Pull Request
409
609
 
410
610
  ## ๐Ÿ“„ License
411
611
 
412
- MIT License - see LICENSE file for details.
612
+ MIT License - see [LICENSE](LICENSE) file for details.
413
613
 
414
614
  ## ๐Ÿ™ Acknowledgments
415
615
 
416
- - Uses [Chance.js](https://chancejs.com/) for random number generation
616
+ - [Chance.js](https://chancejs.com/) for random number generation
417
617
  - Custom Markov chain implementation for procedural text generation
418
618
 
419
- ## ๐Ÿ”ฎ Future Enhancements
420
-
421
- - **Thematic Training Sets**: Fantasy, Sci-fi, Historical themes
422
- - **Multi-language Support**: Generate events in different languages
423
- - **Event Chains**: Multi-part event sequences
424
- - **Dynamic Difficulty**: Events scale with player power level
425
- - **Cultural Context**: Region-specific event generation
426
- - **Time-based Events**: Events that change over time
427
-
428
619
  ---
429
620
 
430
621
  **Generate infinite adventures with RPG Event Generator!** โš”๏ธ๐Ÿ“šโœจ