Files
Genarrative/src/services/storyEngine/actPlanner.ts
高物 ddcb5d5c8c
Some checks failed
CI / verify (push) Has been cancelled
Rework story engine flow and reorganize project docs
2026-04-06 23:19:00 +08:00

70 lines
2.0 KiB
TypeScript

import type { ActState, ChapterState, GameState } from '../../types';
function resolveActIndex(chapterState: ChapterState | null | undefined) {
if (!chapterState) return 0;
if (chapterState.stage === 'climax' || chapterState.stage === 'aftermath') return 2;
if (chapterState.stage === 'turning_point') return 1;
return 0;
}
export function buildActPlan(params: {
state: GameState;
}) {
const primaryThreads = params.state.storyEngineMemory?.activeThreadIds ?? [];
return [
{
id: 'act-1',
title: '第一幕·起线',
actIndex: 0,
theme: '铺陈与引线',
primaryThreadIds: primaryThreads.slice(0, 2),
status: 'opening',
},
{
id: 'act-2',
title: '第二幕·扩张',
actIndex: 1,
theme: '冲突升级',
primaryThreadIds: primaryThreads.slice(0, 3),
status: 'midgame',
},
{
id: 'act-3',
title: '第三幕·收束',
actIndex: 2,
theme: '决战与余波',
primaryThreadIds: primaryThreads.slice(0, 3),
status: 'finale',
},
] satisfies ActState[];
}
export function resolveCurrentActState(params: {
state: GameState;
chapterState?: ChapterState | null;
}) {
const chapterState = params.chapterState ?? params.state.chapterState ?? null;
const actIndex = resolveActIndex(chapterState);
const actPlan = buildActPlan(params);
const candidate = actPlan[actIndex] ?? actPlan[0];
if (!candidate) return null;
return {
...candidate,
theme: chapterState?.theme ?? candidate.theme,
primaryThreadIds: chapterState?.primaryThreadIds ?? candidate.primaryThreadIds,
status:
chapterState?.stage === 'opening'
? 'opening'
: chapterState?.stage === 'expansion'
? 'midgame'
: chapterState?.stage === 'turning_point'
? 'late_game'
: chapterState?.stage === 'climax'
? 'finale'
: chapterState?.stage === 'aftermath'
? 'resolved'
: candidate.status,
} satisfies ActState;
}