StoryForge - Interactive Storytelling Features

Note: We'll now focus on implementing interactive storytelling features that allow users to influence the direction of the story. This system will integrate with our existing story generation framework and dynamic plotting system.

Interactive Storytelling System

Let's create an interactive storytelling system that can work alongside our existing APIs:


// interactiveStorytelling.js

const { StoryElement } = require('./storyElements');

class Choice extends StoryElement {
  constructor(id, text, consequences) {
    super(id, { text, consequences });
  }

  execute(context) {
    this.properties.consequences.forEach(consequence => consequence(context));
  }
}

class InteractionPoint extends StoryElement {
  constructor(id, description, choices) {
    super(id, { description, choices });
  }

  addChoice(choice) {
    this.properties.choices.push(choice);
  }

  getChoices() {
    return this.properties.choices;
  }
}

class InteractiveStoryManager {
  constructor(storyGenerator) {
    this.storyGenerator = storyGenerator;
    this.currentInteractionPoint = null;
  }

  createInteractionPoint(id, description, choices) {
    return new InteractionPoint(id, description, choices.map(c => new Choice(c.id, c.text, c.consequences)));
  }

  setCurrentInteractionPoint(interactionPoint) {
    this.currentInteractionPoint = interactionPoint;
  }

  getCurrentChoices() {
    return this.currentInteractionPoint ? this.currentInteractionPoint.getChoices() : [];
  }

  makeChoice(choiceId) {
    const choice = this.currentInteractionPoint.getChoices().find(c => c.id === choiceId);
    if (choice) {
      choice.execute(this.storyGenerator.context);
      this.currentInteractionPoint = null;
      return true;
    }
    return false;
  }

  generateInteractiveStoryBeat() {
    if (this.currentInteractionPoint) {
      return {
        type: 'interaction',
        content: this.currentInteractionPoint.properties.description,
        choices: this.getCurrentChoices().map(c => ({ id: c.id, text: c.properties.text }))
      };
    } else {
      const beat = this.storyGenerator.generateStoryBeat();
      if (Math.random() < 0.3) { // 30% chance of generating an interaction point
        const interactionPoint = this.generateInteractionPoint(beat);
        this.setCurrentInteractionPoint(interactionPoint);
        return {
          type: 'interaction',
          content: interactionPoint.properties.description,
          choices: this.getCurrentChoices().map(c => ({ id: c.id, text: c.properties.text }))
        };
      }
      return beat;
    }
  }

  generateInteractionPoint(beat) {
    // This is a simplified version. In a real implementation, you'd generate meaningful choices based on the current story state.
    const choices = [
      { id: 'choice1', text: 'Option A', consequences: [ctx => { /* Apply consequences */ }] },
      { id: 'choice2', text: 'Option B', consequences: [ctx => { /* Apply consequences */ }] },
    ];
    return this.createInteractionPoint('interaction1', beat.content, choices);
  }
}

module.exports = {
  Choice,
  InteractionPoint,
  InteractiveStoryManager
};
    

Now, let's integrate this with our enhanced story generator:


// interactiveStoryGenerator.js

const EnhancedStoryGenerator = require('./enhancedStoryGenerator');
const { InteractiveStoryManager } = require('./interactiveStorytelling');

class InteractiveStoryGenerator extends EnhancedStoryGenerator {
  constructor(genreExtension) {
    super(genreExtension);
    this.interactiveManager = new InteractiveStoryManager(this);
  }

  generateStoryBeat() {
    return this.interactiveManager.generateInteractiveStoryBeat();
  }

  makeChoice(choiceId) {
    return this.interactiveManager.makeChoice(choiceId);
  }

  getCurrentChoices() {
    return this.interactiveManager.getCurrentChoices();
  }
}

module.exports = InteractiveStoryGenerator;
    

Usage Example

Here's how you might use the interactive story generator:


// usage.js

const InteractiveStoryGenerator = require('./interactiveStoryGenerator');
const ScienceFictionExtension = require('./genres/scienceFiction');

const generator = new InteractiveStoryGenerator(ScienceFictionExtension);

// Initialize the story
generator.initializeStory(
  'Galactic Frontier',
  { setting: 'Space Colony' },
  [{ name: 'Captain Alex', backstory: 'Veteran space explorer', traits: ['brave', 'resourceful'] }],
  [{ name: 'Alpha Centauri B', type: 'star system', properties: { planets: 3 } }],
  [{ name: 'First Contact', description: 'Discovering alien life', plotPoints: [/* ... */] }]
);

// Generate story beats
let beat = generator.generateStoryBeat();
console.log(beat.content);

while (true) {
  if (beat.type === 'interaction') {
    console.log('Choose an option:');
    beat.choices.forEach(choice => console.log(`${choice.id}: ${choice.text}`));
    
    // In a real application, you'd get user input here
    const choiceId = 'choice1'; // Simulating user choice
    
    generator.makeChoice(choiceId);
  }
  
  beat = generator.generateStoryBeat();
  console.log(beat.content);
  
  // Add some condition to break the loop
}
    

Benefits of the Interactive Storytelling System

Next Steps

With our interactive storytelling features in place, we can move on to other areas of improvement. What would you like to focus on next?