qnce-engine 0.1.0
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/LICENSE +21 -0
- package/README.md +225 -0
- package/dist/cli/audit.d.ts +3 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +76 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +136 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/engine/core.d.ts +46 -0
- package/dist/engine/core.d.ts.map +1 -0
- package/dist/engine/core.js +81 -0
- package/dist/engine/core.js.map +1 -0
- package/dist/engine/demo-story.d.ts +3 -0
- package/dist/engine/demo-story.d.ts.map +1 -0
- package/dist/engine/demo-story.js +112 -0
- package/dist/engine/demo-story.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/examples/quantum-garden.js +99 -0
- package/examples/quantum-garden.ts +99 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ByteSower
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# QNCE Engine
|
|
2
|
+
|
|
3
|
+
**Quantum Narrative Convergence Engine** - A framework-agnostic TypeScript library for creating interactive narrative experiences with quantum-inspired mechanics.
|
|
4
|
+
|
|
5
|
+
## Core Concepts
|
|
6
|
+
|
|
7
|
+
- **Superposition:** Multiple narrative outcomes exist simultaneously until a choice is made
|
|
8
|
+
- **Collapse:** Player choices "collapse" the narrative to a specific path, updating state and flags
|
|
9
|
+
- **Entanglement:** Early decisions affect later outcomes, enabling complex, interconnected stories
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install qnce-engine
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { createQNCEEngine, DEMO_STORY } from 'qnce-engine';
|
|
21
|
+
|
|
22
|
+
// Create engine instance with demo story
|
|
23
|
+
const engine = createQNCEEngine(DEMO_STORY);
|
|
24
|
+
|
|
25
|
+
// Get current narrative state
|
|
26
|
+
const currentNode = engine.getCurrentNode();
|
|
27
|
+
console.log(currentNode.text);
|
|
28
|
+
|
|
29
|
+
// Get available choices
|
|
30
|
+
const choices = engine.getAvailableChoices();
|
|
31
|
+
console.log(choices);
|
|
32
|
+
|
|
33
|
+
// Make a choice
|
|
34
|
+
if (choices.length > 0) {
|
|
35
|
+
engine.selectChoice(choices[0]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check narrative flags
|
|
39
|
+
const flags = engine.getFlags();
|
|
40
|
+
console.log('Current flags:', flags);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Core API
|
|
44
|
+
|
|
45
|
+
### QNCEEngine Class
|
|
46
|
+
|
|
47
|
+
The main engine class for managing narrative state.
|
|
48
|
+
|
|
49
|
+
#### Methods
|
|
50
|
+
|
|
51
|
+
- `getCurrentNode()`: Get the current narrative node
|
|
52
|
+
- `getState()`: Get the complete engine state
|
|
53
|
+
- `getFlags()`: Get current narrative flags
|
|
54
|
+
- `getHistory()`: Get choice history
|
|
55
|
+
- `selectChoice(choice)`: Make a narrative choice
|
|
56
|
+
- `resetNarrative()`: Reset to initial state
|
|
57
|
+
- `loadState(state)`: Load a saved state
|
|
58
|
+
- `checkFlag(name, value?)`: Check flag conditions
|
|
59
|
+
- `getAvailableChoices()`: Get filtered available choices
|
|
60
|
+
|
|
61
|
+
### Factory Functions
|
|
62
|
+
|
|
63
|
+
- `createQNCEEngine(storyData, initialState?)`: Create a new engine instance
|
|
64
|
+
- `loadStoryData(jsonData)`: Load and validate story data from JSON
|
|
65
|
+
|
|
66
|
+
## Story Format
|
|
67
|
+
|
|
68
|
+
Stories are defined using JSON with the following structure:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"initialNodeId": "start",
|
|
73
|
+
"nodes": [
|
|
74
|
+
{
|
|
75
|
+
"id": "start",
|
|
76
|
+
"text": "You stand at a crossroads...",
|
|
77
|
+
"choices": [
|
|
78
|
+
{
|
|
79
|
+
"text": "Go left",
|
|
80
|
+
"nextNodeId": "left_path",
|
|
81
|
+
"flagEffects": { "direction": "left" }
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## CLI Tools
|
|
90
|
+
|
|
91
|
+
### qnce-audit
|
|
92
|
+
|
|
93
|
+
Validate your story structure:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
qnce-audit story.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Features:
|
|
100
|
+
- Checks for missing node references
|
|
101
|
+
- Identifies unreachable nodes
|
|
102
|
+
- Finds dead ends
|
|
103
|
+
- Validates story structure
|
|
104
|
+
|
|
105
|
+
### qnce-init
|
|
106
|
+
|
|
107
|
+
Scaffold a new QNCE project:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
qnce-init my-story
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Creates:
|
|
114
|
+
- Basic story template
|
|
115
|
+
- package.json with QNCE dependencies
|
|
116
|
+
- README with usage instructions
|
|
117
|
+
|
|
118
|
+
## Integration Examples
|
|
119
|
+
|
|
120
|
+
### React Hook
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { createQNCEEngine } from 'qnce-engine';
|
|
124
|
+
import { useState, useEffect } from 'react';
|
|
125
|
+
|
|
126
|
+
function useQNCE(storyData) {
|
|
127
|
+
const [engine] = useState(() => createQNCEEngine(storyData));
|
|
128
|
+
const [currentNode, setCurrentNode] = useState(engine.getCurrentNode());
|
|
129
|
+
const [flags, setFlags] = useState(engine.getFlags());
|
|
130
|
+
|
|
131
|
+
const selectChoice = (choice) => {
|
|
132
|
+
engine.selectChoice(choice);
|
|
133
|
+
setCurrentNode(engine.getCurrentNode());
|
|
134
|
+
setFlags(engine.getFlags());
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return { currentNode, flags, selectChoice };
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Vue Composition API
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { createQNCEEngine } from 'qnce-engine';
|
|
145
|
+
import { ref, reactive } from 'vue';
|
|
146
|
+
|
|
147
|
+
export function useQNCE(storyData) {
|
|
148
|
+
const engine = createQNCEEngine(storyData);
|
|
149
|
+
const currentNode = ref(engine.getCurrentNode());
|
|
150
|
+
const flags = reactive(engine.getFlags());
|
|
151
|
+
|
|
152
|
+
const selectChoice = (choice) => {
|
|
153
|
+
engine.selectChoice(choice);
|
|
154
|
+
currentNode.value = engine.getCurrentNode();
|
|
155
|
+
Object.assign(flags, engine.getFlags());
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return { currentNode, flags, selectChoice };
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Node.js CLI
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { createQNCEEngine, loadStoryData } from 'qnce-engine';
|
|
166
|
+
import { readFileSync } from 'fs';
|
|
167
|
+
import * as readline from 'readline';
|
|
168
|
+
|
|
169
|
+
const storyData = loadStoryData(JSON.parse(readFileSync('story.json', 'utf-8')));
|
|
170
|
+
const engine = createQNCEEngine(storyData);
|
|
171
|
+
|
|
172
|
+
async function playStory() {
|
|
173
|
+
const rl = readline.createInterface({
|
|
174
|
+
input: process.stdin,
|
|
175
|
+
output: process.stdout
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
while (true) {
|
|
179
|
+
const node = engine.getCurrentNode();
|
|
180
|
+
console.log('\n' + node.text);
|
|
181
|
+
|
|
182
|
+
if (node.choices.length === 0) break;
|
|
183
|
+
|
|
184
|
+
node.choices.forEach((choice, i) => {
|
|
185
|
+
console.log(`${i + 1}. ${choice.text}`);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Get user input and make choice...
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Development
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Clone and setup
|
|
197
|
+
git clone https://github.com/ByteSower/qnce-engine.git
|
|
198
|
+
cd qnce-engine
|
|
199
|
+
npm install
|
|
200
|
+
|
|
201
|
+
# Build
|
|
202
|
+
npm run build
|
|
203
|
+
|
|
204
|
+
# Watch mode
|
|
205
|
+
npm run build:watch
|
|
206
|
+
|
|
207
|
+
# Lint
|
|
208
|
+
npm run lint
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT - See LICENSE file for details.
|
|
214
|
+
|
|
215
|
+
## Contributing
|
|
216
|
+
|
|
217
|
+
1. Fork the repository
|
|
218
|
+
2. Create a feature branch
|
|
219
|
+
3. Make your changes
|
|
220
|
+
4. Add tests if applicable
|
|
221
|
+
5. Submit a pull request
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
**QNCE Engine** - Empowering interactive narratives with quantum-inspired mechanics.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/cli/audit.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { loadStoryData } from '../engine/core.js';
|
|
4
|
+
/**
|
|
5
|
+
* QNCE Audit CLI Tool
|
|
6
|
+
* Validates narrative structure and checks for loops, dead ends, etc.
|
|
7
|
+
*/
|
|
8
|
+
function auditStory(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
console.log(`š Auditing QNCE story: ${filePath}`);
|
|
11
|
+
const jsonData = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
12
|
+
const storyData = loadStoryData(jsonData);
|
|
13
|
+
// Basic validation
|
|
14
|
+
console.log(`š Story contains ${storyData.nodes.length} nodes`);
|
|
15
|
+
console.log(`š Initial node: ${storyData.initialNodeId}`);
|
|
16
|
+
// Check for missing nodes
|
|
17
|
+
const nodeIds = new Set(storyData.nodes.map(n => n.id));
|
|
18
|
+
const referencedIds = new Set();
|
|
19
|
+
storyData.nodes.forEach(node => {
|
|
20
|
+
node.choices.forEach(choice => {
|
|
21
|
+
referencedIds.add(choice.nextNodeId);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
// Find dead ends
|
|
25
|
+
const deadEnds = storyData.nodes.filter(node => node.choices.length === 0);
|
|
26
|
+
console.log(`š Dead ends found: ${deadEnds.length}`);
|
|
27
|
+
deadEnds.forEach(node => console.log(` - ${node.id}: "${node.text.slice(0, 50)}..."`));
|
|
28
|
+
// Find missing node references
|
|
29
|
+
const missingNodes = Array.from(referencedIds).filter(id => !nodeIds.has(id));
|
|
30
|
+
if (missingNodes.length > 0) {
|
|
31
|
+
console.log(`ā Missing nodes referenced:`);
|
|
32
|
+
missingNodes.forEach(id => console.log(` - ${id}`));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.log(`ā
All node references are valid`);
|
|
36
|
+
}
|
|
37
|
+
// Find unreachable nodes
|
|
38
|
+
const reachableIds = new Set();
|
|
39
|
+
const toVisit = [storyData.initialNodeId];
|
|
40
|
+
while (toVisit.length > 0) {
|
|
41
|
+
const currentId = toVisit.pop();
|
|
42
|
+
if (reachableIds.has(currentId))
|
|
43
|
+
continue;
|
|
44
|
+
reachableIds.add(currentId);
|
|
45
|
+
const node = storyData.nodes.find(n => n.id === currentId);
|
|
46
|
+
if (node) {
|
|
47
|
+
node.choices.forEach(choice => {
|
|
48
|
+
if (!reachableIds.has(choice.nextNodeId)) {
|
|
49
|
+
toVisit.push(choice.nextNodeId);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const unreachableNodes = storyData.nodes.filter(node => !reachableIds.has(node.id));
|
|
55
|
+
if (unreachableNodes.length > 0) {
|
|
56
|
+
console.log(`ā ļø Unreachable nodes found: ${unreachableNodes.length}`);
|
|
57
|
+
unreachableNodes.forEach(node => console.log(` - ${node.id}`));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.log(`ā
All nodes are reachable`);
|
|
61
|
+
}
|
|
62
|
+
console.log(`⨠Audit complete!`);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error(`ā Error auditing story:`, error);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// CLI entry point
|
|
70
|
+
const filePath = process.argv[2];
|
|
71
|
+
if (!filePath) {
|
|
72
|
+
console.log('Usage: qnce-audit <story-file.json>');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
auditStory(filePath);
|
|
76
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/cli/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":""}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { writeFileSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
/**
|
|
5
|
+
* QNCE Init CLI Tool
|
|
6
|
+
* Scaffolds a new QNCE story project
|
|
7
|
+
*/
|
|
8
|
+
function initProject(projectName) {
|
|
9
|
+
try {
|
|
10
|
+
console.log(`š Initializing QNCE project: ${projectName}`);
|
|
11
|
+
// Create project directory
|
|
12
|
+
mkdirSync(projectName, { recursive: true });
|
|
13
|
+
// Create basic story template
|
|
14
|
+
const storyTemplate = {
|
|
15
|
+
initialNodeId: 'start',
|
|
16
|
+
nodes: [
|
|
17
|
+
{
|
|
18
|
+
id: 'start',
|
|
19
|
+
text: 'Welcome to your QNCE story! This is the beginning.',
|
|
20
|
+
choices: [
|
|
21
|
+
{
|
|
22
|
+
text: 'Continue',
|
|
23
|
+
nextNodeId: 'middle',
|
|
24
|
+
flagEffects: { started: true }
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'middle',
|
|
30
|
+
text: 'You are now in the middle of your story. Where do you want to go next?',
|
|
31
|
+
choices: [
|
|
32
|
+
{
|
|
33
|
+
text: 'Go to the ending',
|
|
34
|
+
nextNodeId: 'end',
|
|
35
|
+
flagEffects: { visitedMiddle: true }
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
text: 'Go back to start',
|
|
39
|
+
nextNodeId: 'start',
|
|
40
|
+
flagEffects: { wentBack: true }
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'end',
|
|
46
|
+
text: 'Congratulations! You have reached the end of your story.',
|
|
47
|
+
choices: []
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
};
|
|
51
|
+
// Write story file
|
|
52
|
+
const storyPath = join(projectName, 'story.json');
|
|
53
|
+
writeFileSync(storyPath, JSON.stringify(storyTemplate, null, 2));
|
|
54
|
+
// Create package.json
|
|
55
|
+
const packageJson = {
|
|
56
|
+
name: projectName,
|
|
57
|
+
version: '1.0.0',
|
|
58
|
+
description: 'A QNCE interactive narrative',
|
|
59
|
+
main: 'story.json',
|
|
60
|
+
scripts: {
|
|
61
|
+
audit: 'qnce-audit story.json'
|
|
62
|
+
},
|
|
63
|
+
dependencies: {
|
|
64
|
+
'qnce-engine': '^0.1.0'
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const packagePath = join(projectName, 'package.json');
|
|
68
|
+
writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
|
|
69
|
+
// Create README
|
|
70
|
+
const readme = `# ${projectName}
|
|
71
|
+
|
|
72
|
+
A QNCE (Quantum Narrative Convergence Engine) interactive story.
|
|
73
|
+
|
|
74
|
+
## Getting Started
|
|
75
|
+
|
|
76
|
+
1. Install dependencies:
|
|
77
|
+
\`\`\`bash
|
|
78
|
+
npm install
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
2. Edit your story in \`story.json\`
|
|
82
|
+
|
|
83
|
+
3. Audit your story for issues:
|
|
84
|
+
\`\`\`bash
|
|
85
|
+
npm run audit
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
## Story Structure
|
|
89
|
+
|
|
90
|
+
Your story is defined in \`story.json\` with the following structure:
|
|
91
|
+
|
|
92
|
+
- \`initialNodeId\`: The starting node of your story
|
|
93
|
+
- \`nodes\`: Array of narrative nodes, each with:
|
|
94
|
+
- \`id\`: Unique identifier
|
|
95
|
+
- \`text\`: The narrative text
|
|
96
|
+
- \`choices\`: Array of choices leading to other nodes
|
|
97
|
+
|
|
98
|
+
## Using QNCE Engine
|
|
99
|
+
|
|
100
|
+
\`\`\`javascript
|
|
101
|
+
import { createQNCEEngine, loadStoryData } from 'qnce-engine';
|
|
102
|
+
import storyData from './story.json';
|
|
103
|
+
|
|
104
|
+
const engine = createQNCEEngine(storyData);
|
|
105
|
+
const currentNode = engine.getCurrentNode();
|
|
106
|
+
console.log(currentNode.text);
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
Happy storytelling!
|
|
110
|
+
`;
|
|
111
|
+
const readmePath = join(projectName, 'README.md');
|
|
112
|
+
writeFileSync(readmePath, readme);
|
|
113
|
+
console.log(`ā
Project created successfully!`);
|
|
114
|
+
console.log(`š Files created:`);
|
|
115
|
+
console.log(` - ${storyPath}`);
|
|
116
|
+
console.log(` - ${packagePath}`);
|
|
117
|
+
console.log(` - ${readmePath}`);
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log(`šÆ Next steps:`);
|
|
120
|
+
console.log(` cd ${projectName}`);
|
|
121
|
+
console.log(` npm install`);
|
|
122
|
+
console.log(` npm run audit`);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error(`ā Error creating project:`, error);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// CLI entry point
|
|
130
|
+
const projectName = process.argv[2];
|
|
131
|
+
if (!projectName) {
|
|
132
|
+
console.log('Usage: qnce-init <project-name>');
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
initProject(projectName);
|
|
136
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface Choice {
|
|
2
|
+
text: string;
|
|
3
|
+
nextNodeId: string;
|
|
4
|
+
flagEffects?: Record<string, any>;
|
|
5
|
+
}
|
|
6
|
+
export interface NarrativeNode {
|
|
7
|
+
id: string;
|
|
8
|
+
text: string;
|
|
9
|
+
choices: Choice[];
|
|
10
|
+
}
|
|
11
|
+
export interface QNCEState {
|
|
12
|
+
currentNodeId: string;
|
|
13
|
+
flags: Record<string, any>;
|
|
14
|
+
history: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface StoryData {
|
|
17
|
+
nodes: NarrativeNode[];
|
|
18
|
+
initialNodeId: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* QNCE Engine - Core narrative state management
|
|
22
|
+
* Framework agnostic implementation
|
|
23
|
+
*/
|
|
24
|
+
export declare class QNCEEngine {
|
|
25
|
+
private state;
|
|
26
|
+
private storyData;
|
|
27
|
+
constructor(storyData: StoryData, initialState?: Partial<QNCEState>);
|
|
28
|
+
getCurrentNode(): NarrativeNode;
|
|
29
|
+
getState(): QNCEState;
|
|
30
|
+
getFlags(): Record<string, any>;
|
|
31
|
+
getHistory(): string[];
|
|
32
|
+
selectChoice(choice: Choice): void;
|
|
33
|
+
resetNarrative(): void;
|
|
34
|
+
loadState(state: QNCEState): void;
|
|
35
|
+
checkFlag(flagName: string, expectedValue?: any): boolean;
|
|
36
|
+
getAvailableChoices(): Choice[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Factory function to create a QNCE engine instance
|
|
40
|
+
*/
|
|
41
|
+
export declare function createQNCEEngine(storyData: StoryData, initialState?: Partial<QNCEState>): QNCEEngine;
|
|
42
|
+
/**
|
|
43
|
+
* Load story data from JSON
|
|
44
|
+
*/
|
|
45
|
+
export declare function loadStoryData(jsonData: any): StoryData;
|
|
46
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/engine/core.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAUD;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,SAAS,CAAY;gBAEjB,SAAS,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;IASnE,cAAc,IAAI,aAAa;IAI/B,QAAQ,IAAI,SAAS;IAIrB,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI/B,UAAU,IAAI,MAAM,EAAE;IAItB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IASlC,cAAc,IAAI,IAAI;IAMtB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAKjC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,GAAG,GAAG,OAAO;IAQzD,mBAAmB,IAAI,MAAM,EAAE;CAOhC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,UAAU,CAEpG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,CAGtD"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// QNCE Core Engine - Framework Agnostic
|
|
2
|
+
// Quantum Narrative Convergence Engine
|
|
3
|
+
// Demo narrative data moved to demo-story.ts
|
|
4
|
+
function findNode(nodes, id) {
|
|
5
|
+
const node = nodes.find(n => n.id === id);
|
|
6
|
+
if (!node)
|
|
7
|
+
throw new Error(`Node not found: ${id}`);
|
|
8
|
+
return node;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* QNCE Engine - Core narrative state management
|
|
12
|
+
* Framework agnostic implementation
|
|
13
|
+
*/
|
|
14
|
+
export class QNCEEngine {
|
|
15
|
+
state;
|
|
16
|
+
storyData;
|
|
17
|
+
constructor(storyData, initialState) {
|
|
18
|
+
this.storyData = storyData;
|
|
19
|
+
this.state = {
|
|
20
|
+
currentNodeId: initialState?.currentNodeId || storyData.initialNodeId,
|
|
21
|
+
flags: initialState?.flags || {},
|
|
22
|
+
history: initialState?.history || [storyData.initialNodeId],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
getCurrentNode() {
|
|
26
|
+
return findNode(this.storyData.nodes, this.state.currentNodeId);
|
|
27
|
+
}
|
|
28
|
+
getState() {
|
|
29
|
+
return { ...this.state };
|
|
30
|
+
}
|
|
31
|
+
getFlags() {
|
|
32
|
+
return { ...this.state.flags };
|
|
33
|
+
}
|
|
34
|
+
getHistory() {
|
|
35
|
+
return [...this.state.history];
|
|
36
|
+
}
|
|
37
|
+
selectChoice(choice) {
|
|
38
|
+
this.state.currentNodeId = choice.nextNodeId;
|
|
39
|
+
this.state.history.push(choice.nextNodeId);
|
|
40
|
+
if (choice.flagEffects) {
|
|
41
|
+
this.state.flags = { ...this.state.flags, ...choice.flagEffects };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
resetNarrative() {
|
|
45
|
+
this.state.currentNodeId = this.storyData.initialNodeId;
|
|
46
|
+
this.state.flags = {};
|
|
47
|
+
this.state.history = [this.storyData.initialNodeId];
|
|
48
|
+
}
|
|
49
|
+
loadState(state) {
|
|
50
|
+
this.state = { ...state };
|
|
51
|
+
}
|
|
52
|
+
// Utility method for checking flag conditions
|
|
53
|
+
checkFlag(flagName, expectedValue) {
|
|
54
|
+
if (expectedValue === undefined) {
|
|
55
|
+
return this.state.flags[flagName] !== undefined;
|
|
56
|
+
}
|
|
57
|
+
return this.state.flags[flagName] === expectedValue;
|
|
58
|
+
}
|
|
59
|
+
// Get available choices (with potential flag-based filtering)
|
|
60
|
+
getAvailableChoices() {
|
|
61
|
+
const currentNode = this.getCurrentNode();
|
|
62
|
+
return currentNode.choices.filter(choice => {
|
|
63
|
+
// Future: Add flag-based choice filtering logic here
|
|
64
|
+
return true;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Factory function to create a QNCE engine instance
|
|
70
|
+
*/
|
|
71
|
+
export function createQNCEEngine(storyData, initialState) {
|
|
72
|
+
return new QNCEEngine(storyData, initialState);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Load story data from JSON
|
|
76
|
+
*/
|
|
77
|
+
export function loadStoryData(jsonData) {
|
|
78
|
+
// Add validation here in the future
|
|
79
|
+
return jsonData;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/engine/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-story.d.ts","sourceRoot":"","sources":["../../src/engine/demo-story.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,eAAO,MAAM,UAAU,EAAE,SA6GxB,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Demo narrative data for QNCE Engine
|
|
2
|
+
export const DEMO_STORY = {
|
|
3
|
+
initialNodeId: 'start',
|
|
4
|
+
nodes: [
|
|
5
|
+
{
|
|
6
|
+
id: 'start',
|
|
7
|
+
text: 'You stand at a crossroads. Do you go left or right?',
|
|
8
|
+
choices: [
|
|
9
|
+
{ text: 'Left', nextNodeId: 'river', flagEffects: { wentLeft: true } },
|
|
10
|
+
{ text: 'Right', nextNodeId: 'mountain', flagEffects: { wentLeft: false } },
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'river',
|
|
15
|
+
text: 'You encounter a river. Do you swim or build a raft?',
|
|
16
|
+
choices: [
|
|
17
|
+
{ text: 'Swim', nextNodeId: 'swim', flagEffects: { gotWet: true } },
|
|
18
|
+
{ text: 'Build a raft', nextNodeId: 'raft', flagEffects: { gotWet: false } },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'mountain',
|
|
23
|
+
text: 'You find a mountain. Do you climb or go around?',
|
|
24
|
+
choices: [
|
|
25
|
+
{ text: 'Climb', nextNodeId: 'climb', flagEffects: { climbed: true } },
|
|
26
|
+
{ text: 'Go around', nextNodeId: 'village', flagEffects: { climbed: false } },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
// --- Expanded Narrative Branches ---
|
|
30
|
+
{
|
|
31
|
+
id: 'swim',
|
|
32
|
+
text: 'You swim across and reach the other side, but you are soaked and cold. Ahead, you see a cave and a campfire.',
|
|
33
|
+
choices: [
|
|
34
|
+
{ text: 'Warm up by the campfire', nextNodeId: 'campfire', flagEffects: { warmedUp: true } },
|
|
35
|
+
{ text: 'Explore the cave', nextNodeId: 'cave', flagEffects: { exploredCave: true } },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'raft',
|
|
40
|
+
text: 'You build a raft and float safely. On the far bank, a merchant greets you.',
|
|
41
|
+
choices: [
|
|
42
|
+
{ text: 'Trade with the merchant', nextNodeId: 'merchant', flagEffects: { metMerchant: true } },
|
|
43
|
+
{ text: 'Ignore and continue', nextNodeId: 'forest', flagEffects: { metMerchant: false } },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'climb',
|
|
48
|
+
text: 'You climb and see a vast land. The wind is strong. Do you signal for help or descend?',
|
|
49
|
+
choices: [
|
|
50
|
+
{ text: 'Signal for help', nextNodeId: 'signal', flagEffects: { signaled: true } },
|
|
51
|
+
{ text: 'Descend', nextNodeId: 'forest', flagEffects: { signaled: false } },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'village',
|
|
56
|
+
text: 'You go around and find a village. The villagers are wary. Do you introduce yourself or sneak past?',
|
|
57
|
+
choices: [
|
|
58
|
+
{ text: 'Introduce yourself', nextNodeId: 'welcome', flagEffects: { welcomed: true } },
|
|
59
|
+
{ text: 'Sneak past', nextNodeId: 'forest', flagEffects: { welcomed: false } },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
// --- New Unique Outcomes & Entanglement ---
|
|
63
|
+
{
|
|
64
|
+
id: 'campfire',
|
|
65
|
+
text: 'You warm up by the fire. A traveler offers you advice. (Success!)',
|
|
66
|
+
choices: [],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'cave',
|
|
70
|
+
text: 'Inside the cave, you find ancient markings. Suddenly, you slip and must return to the river bank. (Loop)',
|
|
71
|
+
choices: [
|
|
72
|
+
{ text: 'Return to river', nextNodeId: 'river', flagEffects: { slipped: true } },
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'merchant',
|
|
77
|
+
text: 'The merchant gives you a mysterious key. (Reward!)',
|
|
78
|
+
choices: [],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'forest',
|
|
82
|
+
text: 'You enter a dense forest. If you met the merchant, you can unlock a shortcut.',
|
|
83
|
+
choices: [
|
|
84
|
+
{ text: 'Use the key (if you have it)', nextNodeId: 'shortcut', flagEffects: { usedKey: true } },
|
|
85
|
+
{ text: 'Push through the forest', nextNodeId: 'lost', flagEffects: { usedKey: false } },
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'signal',
|
|
90
|
+
text: 'Your signal is seen! A rescue party arrives. (Success!)',
|
|
91
|
+
choices: [],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'welcome',
|
|
95
|
+
text: 'The villagers welcome you and offer food. (Success!)',
|
|
96
|
+
choices: [],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'shortcut',
|
|
100
|
+
text: 'You use the key to unlock a hidden path and escape the forest. (Success!)',
|
|
101
|
+
choices: [],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'lost',
|
|
105
|
+
text: 'You get lost in the forest. (Failure/Loop)',
|
|
106
|
+
choices: [
|
|
107
|
+
{ text: 'Try to find your way back', nextNodeId: 'forest', flagEffects: { triedAgain: true } },
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=demo-story.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-story.js","sourceRoot":"","sources":["../../src/engine/demo-story.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,4BAA4B;AAC5B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,aAAa,EAKd,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Example: Complete QNCE Engine Integration
|
|
2
|
+
import { createQNCEEngine } from '../dist/index.js';
|
|
3
|
+
|
|
4
|
+
// Define a custom story
|
|
5
|
+
const customStory = {
|
|
6
|
+
initialNodeId: "garden_entrance",
|
|
7
|
+
nodes: [
|
|
8
|
+
{
|
|
9
|
+
id: "garden_entrance",
|
|
10
|
+
text: "You approach a shimmering garden where flowers exist in quantum superposition, both blooming and wilted until observed. What do you do?",
|
|
11
|
+
choices: [
|
|
12
|
+
{
|
|
13
|
+
text: "Observe the flowers carefully",
|
|
14
|
+
nextNodeId: "collapsed_garden",
|
|
15
|
+
flagEffects: { flowersObserved: true }
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
text: "Enter with eyes closed",
|
|
19
|
+
nextNodeId: "superposition_garden",
|
|
20
|
+
flagEffects: { preservedSuperposition: true }
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "collapsed_garden",
|
|
26
|
+
text: "Your observation collapses the quantum state. The flowers are now definitively wilted, their beauty lost to the measurement.",
|
|
27
|
+
choices: [
|
|
28
|
+
{
|
|
29
|
+
text: "Plant new seeds",
|
|
30
|
+
nextNodeId: "rebirth",
|
|
31
|
+
flagEffects: { plantedSeeds: true }
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "superposition_garden",
|
|
37
|
+
text: "Moving blindly, you preserve the flowers' superposition. You feel their quantum essence - simultaneously beautiful and decayed.",
|
|
38
|
+
choices: [
|
|
39
|
+
{
|
|
40
|
+
text: "Meditate in the quantum space",
|
|
41
|
+
nextNodeId: "enlightenment",
|
|
42
|
+
flagEffects: { achievedEnlightenment: true }
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "rebirth",
|
|
48
|
+
text: "Your seeds grow instantly, creating new quantum flowers. The cycle begins anew.",
|
|
49
|
+
choices: []
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "enlightenment",
|
|
53
|
+
text: "You achieve quantum consciousness, understanding that observation and preservation can coexist.",
|
|
54
|
+
choices: []
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Create and use the engine
|
|
60
|
+
const engine = createQNCEEngine(customStory);
|
|
61
|
+
|
|
62
|
+
// Interactive session example
|
|
63
|
+
function playSession() {
|
|
64
|
+
console.log(`š Welcome to "The Quantum Garden"`);
|
|
65
|
+
console.log(`š A tale of superposition and choice\n`);
|
|
66
|
+
|
|
67
|
+
while (true) {
|
|
68
|
+
const node = engine.getCurrentNode();
|
|
69
|
+
console.log(`š ${node.text}\n`);
|
|
70
|
+
|
|
71
|
+
const choices = engine.getAvailableChoices();
|
|
72
|
+
if (choices.length === 0) {
|
|
73
|
+
console.log("š Story Complete!");
|
|
74
|
+
console.log("Final state:", engine.getFlags());
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Display choices
|
|
79
|
+
choices.forEach((choice, index) => {
|
|
80
|
+
console.log(`${index + 1}. ${choice.text}`);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// For demo, select first choice
|
|
84
|
+
const selected = choices[0];
|
|
85
|
+
console.log(`\nā”ļø Selecting: "${selected.text}"\n`);
|
|
86
|
+
engine.selectChoice(selected);
|
|
87
|
+
|
|
88
|
+
// Show state changes
|
|
89
|
+
const flags = engine.getFlags();
|
|
90
|
+
if (Object.keys(flags).length > 0) {
|
|
91
|
+
console.log("š·ļø Updated flags:", flags, "\n");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log("---\n");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Run the demo
|
|
99
|
+
playSession();
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Example: Complete QNCE Engine Integration (TypeScript)
|
|
2
|
+
import { createQNCEEngine, type StoryData } from 'qnce-engine';
|
|
3
|
+
|
|
4
|
+
// Define a custom story
|
|
5
|
+
const customStory: StoryData = {
|
|
6
|
+
initialNodeId: "garden_entrance",
|
|
7
|
+
nodes: [
|
|
8
|
+
{
|
|
9
|
+
id: "garden_entrance",
|
|
10
|
+
text: "You approach a shimmering garden where flowers exist in quantum superposition, both blooming and wilted until observed. What do you do?",
|
|
11
|
+
choices: [
|
|
12
|
+
{
|
|
13
|
+
text: "Observe the flowers carefully",
|
|
14
|
+
nextNodeId: "collapsed_garden",
|
|
15
|
+
flagEffects: { flowersObserved: true }
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
text: "Enter with eyes closed",
|
|
19
|
+
nextNodeId: "superposition_garden",
|
|
20
|
+
flagEffects: { preservedSuperposition: true }
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "collapsed_garden",
|
|
26
|
+
text: "Your observation collapses the quantum state. The flowers are now definitively wilted, their beauty lost to the measurement.",
|
|
27
|
+
choices: [
|
|
28
|
+
{
|
|
29
|
+
text: "Plant new seeds",
|
|
30
|
+
nextNodeId: "rebirth",
|
|
31
|
+
flagEffects: { plantedSeeds: true }
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "superposition_garden",
|
|
37
|
+
text: "Moving blindly, you preserve the flowers' superposition. You feel their quantum essence - simultaneously beautiful and decayed.",
|
|
38
|
+
choices: [
|
|
39
|
+
{
|
|
40
|
+
text: "Meditate in the quantum space",
|
|
41
|
+
nextNodeId: "enlightenment",
|
|
42
|
+
flagEffects: { achievedEnlightenment: true }
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "rebirth",
|
|
48
|
+
text: "Your seeds grow instantly, creating new quantum flowers. The cycle begins anew.",
|
|
49
|
+
choices: []
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "enlightenment",
|
|
53
|
+
text: "You achieve quantum consciousness, understanding that observation and preservation can coexist.",
|
|
54
|
+
choices: []
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Create and use the engine
|
|
60
|
+
const engine = createQNCEEngine(customStory);
|
|
61
|
+
|
|
62
|
+
// Interactive session example
|
|
63
|
+
function playSession(): void {
|
|
64
|
+
console.log(`š Welcome to "The Quantum Garden"`);
|
|
65
|
+
console.log(`š A tale of superposition and choice\n`);
|
|
66
|
+
|
|
67
|
+
while (true) {
|
|
68
|
+
const node = engine.getCurrentNode();
|
|
69
|
+
console.log(`š ${node.text}\n`);
|
|
70
|
+
|
|
71
|
+
const choices = engine.getAvailableChoices();
|
|
72
|
+
if (choices.length === 0) {
|
|
73
|
+
console.log("š Story Complete!");
|
|
74
|
+
console.log("Final state:", engine.getFlags());
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Display choices
|
|
79
|
+
choices.forEach((choice, index) => {
|
|
80
|
+
console.log(`${index + 1}. ${choice.text}`);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// For demo, select first choice
|
|
84
|
+
const selected = choices[0];
|
|
85
|
+
console.log(`\nā”ļø Selecting: "${selected.text}"\n`);
|
|
86
|
+
engine.selectChoice(selected);
|
|
87
|
+
|
|
88
|
+
// Show state changes
|
|
89
|
+
const flags = engine.getFlags();
|
|
90
|
+
if (Object.keys(flags).length > 0) {
|
|
91
|
+
console.log("š·ļø Updated flags:", flags, "\n");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log("---\n");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Run the demo
|
|
99
|
+
playSession();
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "qnce-engine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Core QNCE (Quantum Narrative Convergence Engine) - Framework agnostic narrative engine",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"qnce-audit": "dist/cli/audit.js",
|
|
10
|
+
"qnce-init": "dist/cli/init.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"build:watch": "tsc --watch",
|
|
15
|
+
"lint": "eslint .",
|
|
16
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"narrative",
|
|
21
|
+
"interactive-fiction",
|
|
22
|
+
"quantum-narrative",
|
|
23
|
+
"story-engine",
|
|
24
|
+
"choice-based",
|
|
25
|
+
"typescript"
|
|
26
|
+
],
|
|
27
|
+
"author": "ByteSower",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/ByteSower/qnce-engine.git"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "~5.8.3"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist/**/*",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE",
|
|
42
|
+
"examples/**/*"
|
|
43
|
+
]
|
|
44
|
+
}
|