21 lines
2.7 KiB
TypeScript
21 lines
2.7 KiB
TypeScript
import { writeFileSync } from 'node:fs';
|
||
import { CHAPTERS } from '../src/engine/chapters';
|
||
import type { StoryNode } from '../src/engine/types';
|
||
|
||
function render(node: StoryNode): string {
|
||
const heading = `### ${node.id}${'pointId' in node ? ` / ${node.pointId}` : ''}`;
|
||
switch (node.type) {
|
||
case 'dialogue': return `${heading}\n\n**${node.speaker}**:${node.text}\n\n→ ${node.next}`;
|
||
case 'cutscene': return `${heading}\n\n${node.caption}\n\n→ ${node.next}`;
|
||
case 'chapterEnd': return `${heading}\n\n${node.nextChapter ? `→ ${node.nextChapter}` : '第一季终 → 相处线索报告'}`;
|
||
case 'identity': return `${heading}\n\n${node.prompt}\n\n身份字段由玩家确认,不作人格证据。\n\n→ ${node.next}`;
|
||
case 'choice': return `${heading}\n\n${node.prompt}\n\n${node.options.map((o) => `- **${o.id}**:${o.label}\n → ${o.next}`).join('\n')}\n\n${node.puzzle ? `**谜面与校验**\n\n${node.puzzle.questions.map((q) => `${q.prompt}\n${q.options.map((o, i) => `- ${i + 1}. ${o}${i === q.answer ? '(答案)' : ''}`).join('\n')}`).join('\n\n')}\n\n**三档提示**\n\n${node.puzzle.hints.map((h, i) => `${i + 1}. ${h}`).join('\n')}\n\n` : ''}候选证据:${node.dimensions.join(' / ') || '不参与画像'}。`;
|
||
case 'narration': return `${heading}\n\n**${node.mechanism}**\n\n${node.prompt}\n\n候选证据:${node.dimensions.join(' / ') || '不参与画像'}。\n\n**全部预写变体**\n\n${node.variants.map((v) => `- ${v.signature}:${v.label}`).join('\n')}\n\n${Object.entries(node.followUps).map(([d, text]) => `- 追问 ${d}:${text}`).join('\n')}\n\n→ ${node.next}`;
|
||
}
|
||
}
|
||
|
||
const points = CHAPTERS.flatMap((c) => c.nodes.filter((n) => 'pointId' in n));
|
||
const body = `# 《苍梧疑冢》第一季 · 完整可玩剧本\n\n> 从 content/chapters/chapter1.json 至 chapter9.json 自动生成,手改源 JSON 后运行 pnpm script:season。\n> 含九章全部对白、选项、后续、谜底、提示、讲述变体与跳转;不止一条默认路线。\n> ${points.length} 个主线交互点。条件标记由引擎解释,不向玩家显示。第一幕的十条可选支线全文另见 adaptive-branches.md。\n> 文学与测量设计依据、全季时间线及伏笔核销见 season-design.md;既有第一幕详细创作说明见 act1.md。运行文案以本册同源的 JSON 为准。\n\n${CHAPTERS.map((c) => `## ${c.title} / 第 ${c.act} 幕\n\n${c.nodes.map(render).join('\n\n---\n\n')}`).join('\n\n---\n\n')}`;
|
||
writeFileSync(new URL('../docs/script/season1-full.md', import.meta.url), body + '\n');
|
||
console.log(`完整剧本:${CHAPTERS.length} 章,${points.length} 个主线交互点,${body.length} 字符(包含制作标记)`);
|