qnce-engine
Version:
Core QNCE (Quantum Narrative Convergence Engine) - Framework agnostic narrative engine with performance optimization
340 lines (313 loc) ⢠12.6 kB
text/typescript
// QNCE Branching Demo - Quickstart Example
// Demonstrates Sprint #3 Advanced Branching API capabilities
import { createQNCEEngine } from '../src/engine/core';
import { QNCEStory } from '../src/narrative/branching/models';
// ================================
// Demo Story: "The Mysterious Library"
// ================================
const mysteriousLibraryStory: QNCEStory = {
id: 'mysterious-library',
title: 'The Mysterious Library',
version: '1.0.0',
metadata: {
author: 'QNCE Demo',
description: 'A short interactive story showcasing advanced branching features',
tags: ['mystery', 'exploration', 'choice-driven'],
createDate: new Date(),
lastModified: new Date(),
estimatedPlaytime: 10
},
branchingConfig: {
maxActiveBranches: 8,
branchCacheSize: 30,
enableDynamicInsertion: true,
enableAnalytics: true,
performanceMode: true
},
chapters: [
{
id: 'entrance',
title: 'The Entrance',
description: 'You discover a mysterious library',
flows: [
{
id: 'discovery',
name: 'Library Discovery',
description: 'Finding the library entrance',
nodes: [
{
id: 'street',
text: 'Walking down a foggy street, you notice an old building with warm light spilling from its windows.',
choices: []
},
{
id: 'approach',
text: 'As you approach, you see it\'s a library that doesn\'t appear on any map. The door is slightly ajar.',
choices: []
},
{
id: 'entrance-hall',
text: 'Inside, towering bookshelves stretch impossibly high. Ancient tomes glow softly in the dim light.',
choices: []
}
],
entryPoints: [{ id: 'start', nodeId: 'street', priority: 1 }],
exitPoints: [{ id: 'to-exploration', nodeId: 'entrance-hall' }],
flowType: 'linear',
metadata: { complexity: 2, avgCompletionTime: 4000, playerChoiceCount: 0, aiGeneratedContent: false }
},
{
id: 'careful-exploration',
name: 'Careful Exploration',
description: 'Methodical investigation of the library',
nodes: [
{
id: 'examine-books',
text: 'You carefully examine the ancient books. Their titles shift and change as you watch.',
choices: []
},
{
id: 'find-catalog',
text: 'Behind a particularly large tome, you discover an old card catalog that hums with mysterious energy.',
choices: []
}
],
entryPoints: [{ id: 'careful-start', nodeId: 'examine-books', priority: 1 }],
exitPoints: [{ id: 'catalog-found', nodeId: 'find-catalog' }],
flowType: 'linear',
metadata: { complexity: 4, avgCompletionTime: 6000, playerChoiceCount: 0, aiGeneratedContent: false }
},
{
id: 'bold-exploration',
name: 'Bold Exploration',
description: 'Adventurous investigation of the library',
nodes: [
{
id: 'climb-shelves',
text: 'You boldly climb the towering bookshelves, discovering hidden alcoves and secret passages.',
choices: []
},
{
id: 'secret-room',
text: 'A hidden door opens to reveal a secret reading room where time seems to stand still.',
choices: []
}
],
entryPoints: [{ id: 'bold-start', nodeId: 'climb-shelves', priority: 1 }],
exitPoints: [{ id: 'secrets-revealed', nodeId: 'secret-room' }],
flowType: 'linear',
metadata: { complexity: 5, avgCompletionTime: 5000, playerChoiceCount: 0, aiGeneratedContent: false }
}
],
branches: [
{
id: 'exploration-choice',
name: 'How to Explore',
sourceFlowId: 'discovery',
sourceNodeId: 'entrance-hall',
branchType: 'choice-driven',
branchOptions: [
{
id: 'careful-approach',
targetFlowId: 'careful-exploration',
displayText: 'Carefully examine the books and surroundings',
flagEffects: { 'approach': 'careful', 'attention_to_detail': 8 },
weight: 1.0
},
{
id: 'bold-approach',
targetFlowId: 'bold-exploration',
displayText: 'Boldly explore the towering shelves',
flagEffects: { 'approach': 'bold', 'courage': 9 },
weight: 0.9
}
],
metadata: { usageCount: 0, avgTraversalTime: 0, playerPreference: 0, lastUsed: new Date() }
},
{
id: 'knowledge-gate',
name: 'Knowledge-Based Access',
sourceFlowId: 'careful-exploration',
sourceNodeId: 'find-catalog',
branchType: 'flag-conditional',
branchOptions: [
{
id: 'catalog-expert',
targetFlowId: 'discovery',
targetNodeId: 'entrance-hall',
displayText: 'Use your knowledge to unlock the catalog\'s secrets',
conditions: [
{ type: 'flag', operator: 'greater', key: 'attention_to_detail', value: 7 }
],
flagEffects: { 'catalog_unlocked': true, 'hidden_knowledge': true },
weight: 1.0
},
{
id: 'catalog-basic',
targetFlowId: 'discovery',
targetNodeId: 'entrance-hall',
displayText: 'Browse the catalog carefully',
flagEffects: { 'basic_research': true },
weight: 0.6
}
],
metadata: { usageCount: 0, avgTraversalTime: 0, playerPreference: 0, lastUsed: new Date() }
}
],
prerequisites: {
requiredFlags: {},
requiredChoices: []
},
metadata: {
difficulty: 'easy',
themes: ['mystery', 'exploration', 'knowledge'],
estimatedDuration: 8,
branchComplexity: 6
}
}
]
};
// ================================
// Demo Runner
// ================================
async function runBranchingDemo() {
console.log('š QNCE Branching Demo: The Mysterious Library');
console.log('================================================\n');
// Step 1: Create core engine with matching initial state
const coreStoryData = {
nodes: [
{ id: 'street', text: 'Walking down a foggy street, you notice an old building.', choices: [] }
],
initialNodeId: 'street'
};
const engine = createQNCEEngine(coreStoryData, { currentNodeId: 'street', flags: {}, history: ['street'] });
console.log('ā
Core QNCE engine created');
// Step 2: Enable branching with advanced story
const branchingEngine = engine.enableBranching(mysteriousLibraryStory);
console.log('šæ Advanced branching enabled');
console.log(`š Story: "${mysteriousLibraryStory.title}"`);
console.log(`š Chapters: ${mysteriousLibraryStory.chapters.length}`);
console.log(`š Total branches: ${mysteriousLibraryStory.chapters[0].branches.length}\n`);
// Step 3: Navigate to a branching point
console.log('š Step 1: Navigating to branching point...');
// Move to the entrance hall where branches are available
// First we need to manually transition to where branches exist
console.log('Moving through the story to reach branching points...');
let availableBranches = await branchingEngine.evaluateAvailableBranches();
console.log(`Found ${availableBranches.length} available branches:`);
availableBranches.forEach((branch, i) => {
console.log(` ${i + 1}. "${branch.displayText}"`);
});
// Step 4: Execute a choice
if (availableBranches.length > 0) {
const chosenBranch = availableBranches[0];
console.log(`\nšÆ Executing choice: "${chosenBranch.displayText}"`);
const success = await branchingEngine.executeBranch(chosenBranch.id);
console.log(`Result: ${success ? 'Success! ā
' : 'Failed ā'}`);
// Check for new branches
availableBranches = await branchingEngine.evaluateAvailableBranches();
console.log(`\nš New branches available: ${availableBranches.length}`);
}
// Step 5: Demonstrate conditional branching
console.log('\nšÆ Step 2: Testing conditional branching...');
// This would require navigating to the right node first
// For demo purposes, we'll show the concept
console.log('Conditional branches depend on flags like:');
console.log(' - attention_to_detail > 7 ā Unlock expert catalog access');
console.log(' - courage > 8 ā Access to dangerous areas');
console.log(' - hidden_knowledge = true ā Special story content');
// Step 6: Demonstrate AI integration
console.log('\nš¤ Step 3: AI Branch Generation...');
// Set up AI context for interesting generation
branchingEngine.setAIContext({
playerProfile: {
playStyle: 'explorer',
preferences: {
'mystery_solving': 0.9,
'careful_analysis': 0.8,
'risk_taking': 0.4
},
historicalChoices: ['careful-approach'],
averageDecisionTime: 9000
},
narrativeContext: {
currentTone: 'mysterious-scholarly',
thematicElements: ['ancient-knowledge', 'hidden-secrets'],
characterRelationships: {},
plotTension: 0.6
},
generationHints: {
maxBranchDepth: 2,
desiredComplexity: 7,
contentThemes: ['discovery', 'ancient-wisdom'],
avoidElements: ['violence', 'horror']
}
});
try {
const aiBranches = await branchingEngine.generateAIBranches(3);
console.log(`Generated ${aiBranches.length} AI-enhanced branches:`);
aiBranches.forEach((branch, i) => {
console.log(` ${i + 1}. "${branch.displayText}" (weight: ${branch.weight})`);
});
} catch (error) {
console.log(`AI generation note: ${error.message}`);
}
// Step 7: Analytics demonstration
console.log('\nš Step 4: Analytics & Monitoring...');
const analytics = branchingEngine.getBranchingAnalytics();
console.log(`Branches traversed: ${analytics.totalBranchesTraversed}`);
console.log(`Session duration: ${Date.now() - analytics.sessionStartTime.getTime()}ms`);
console.log(`Popular branches: ${analytics.mostPopularBranches.join(', ') || 'None yet'}`);
// Step 8: Dynamic content demonstration
console.log('\nš§ Step 5: Dynamic Branch Insertion...');
const dynamicBranch = {
type: 'insert' as const,
branchId: 'emergency-exit',
targetLocation: {
chapterId: 'entrance',
flowId: 'discovery',
nodeId: 'entrance-hall',
insertionPoint: 'after' as const
},
payload: {
name: 'Emergency Library Exit',
branchType: 'conditional' as const,
branchOptions: [
{
id: 'quick-exit',
targetFlowId: 'discovery',
displayText: 'Something feels wrong - leave immediately',
conditions: [
{ type: 'flag' as const, operator: 'exists' as const, key: 'danger_sensed', value: true }
],
flagEffects: { 'escaped_safely': true },
weight: 1.0
}
]
},
conditions: [
{ type: 'flag' as const, operator: 'exists' as const, key: 'mysterious_presence', value: true }
]
};
const insertSuccess = await branchingEngine.insertDynamicBranch(dynamicBranch);
console.log(`Dynamic branch insertion: ${insertSuccess ? 'Success! ā
' : 'Failed ā'}`);
// Export data for analysis
console.log('\nš¾ Step 6: Data Export...');
const exportData = branchingEngine.exportBranchingData();
console.log(`Export successful: ${Object.keys(exportData).length} data sections`);
console.log(`Available data: ${Object.keys(exportData).join(', ')}`);
console.log('\nš Demo Complete!');
console.log('=================');
console.log('ā
Core engine integration working');
console.log('ā
Advanced branching operational');
console.log('ā
AI generation ready');
console.log('ā
Analytics tracking');
console.log('ā
Dynamic content management');
console.log('\nš The QNCE Branching API is ready for production use!');
}
// Export for use in other demos
export { mysteriousLibraryStory, runBranchingDemo };
// Run demo if called directly
if (require.main === module) {
runBranchingDemo().catch(console.error);
}