--- id: wiki-2026-0508-procedural-narrative-generation title: Procedural Narrative Generation category: 10_Wiki/Topics status: verified canonical_id: self aliases: [PNG, Story Generation, Computational Narrative, Drama Management] duplicate_of: none source_trust_level: A confidence_score: 0.85 verification_status: applied tags: [narrative, generative-ai, games, llm-applications] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: Python / TypeScript framework: LLM (Claude/GPT) + planner / state machine --- # Procedural Narrative Generation ## 매 한 줄 > **"매 algorithmic story authoring — symbolic planners 부터 LLM-driven emergent narrative 까지"**. 1970s TaleSpin / 1990s drama managers (Façade) 의 lineage; 2019 AI Dungeon 으로 LLM era 시작, 2024-2026 currently agent-based simulation (Smallville, Voyager, Genesis) 에서 narrative emerges from LLM agents interacting in worlds. Hybrid 가 winning: LLM creativity + symbolic constraints. ## 매 핵심 ### 매 paradigm timeline - **Story grammars (1970s-80s)**: Propp's morphology, Rumelhart, TaleSpin (Meehan 1977). - **Planning-based (1990s-2010s)**: STRIPS planners author plot (IPOCL, MEXICA). - **Drama management (2000s)**: Façade (Mateas & Stern 2005) reactive narrative. - **Neural (2017-2020)**: GPT-2/3 generated stories, Plug-and-Play LMs. - **AI Dungeon era (2019-)**: open-ended LLM-driven IF. - **Agent simulation (2023-2026)**: Park's Smallville, Voyager, Genesis world model — believable agents whose interactions form narrative. ### 매 challenges 1. **Coherence**: long-range plot consistency (LLMs forget). 2. **Causality**: events must causally connect. 3. **Character agency**: characters with goals/personalities, not just templates. 4. **Author's vs character's intent**: meta-level narrative goals vs in-world goals. 5. **Tellability**: not every simulation is a good story. ### 매 modern hybrid stack - **World model**: structured state (locations, items, NPCs, relationships). - **LLM as narrator**: takes state + recent events → next beat. - **Symbolic planner**: enforces causal constraints, beats arc. - **Memory / retrieval**: vector DB of past events for consistency. - **Drama manager**: monitors arc (rising/falling tension), nudges plot. ## 💻 패턴 ### LLM beat generator with state ```python def generate_beat(state, history, beat_target): prompt = f"""You are a narrator. Current state: Characters: {state.characters} Location: {state.location} Inventory: {state.inventory} Recent events: {history[-5:]} Beat target: {beat_target} # e.g., "rising tension", "reveal villain" Generate the next narrative beat (2-3 sentences) and any state changes as JSON.""" resp = claude.messages.create( model="claude-opus-4-7", max_tokens=400, messages=[{"role": "user", "content": prompt}], ) return parse(resp.content[0].text) ``` ### Story-arc drama manager (Freytag) ```python ARC = ["exposition", "rising_action", "climax", "falling_action", "resolution"] class DramaManager: def __init__(self, n_beats=20): # Map beat index to arc stage self.targets = ([ARC[0]] * 3 + [ARC[1]] * 8 + [ARC[2]] * 2 + [ARC[3]] * 4 + [ARC[4]] * 3) def next_target(self, beat_idx, tension_so_far): target = self.targets[beat_idx] if target == "rising_action" and tension_so_far < 0.3: return "rising_action_inject_conflict" return target ``` ### Goal-based character agent ```python class CharacterAgent: def __init__(self, name, traits, goals): self.name, self.traits, self.goals = name, traits, goals self.memory = [] # recent observations def choose_action(self, world_state): # LLM call: given personality + memory + state, pick action prompt = f"""You are {self.name}. Traits: {self.traits}. Active goals: {self.goals}. Recent: {self.memory[-10:]}. World: {world_state}. What do you do next? Output: action(target, args).""" return llm(prompt) ``` ### Causal consistency check ```python def verify_beat(beat, state): """Reject beats that violate world rules.""" issues = [] for change in beat.state_changes: if change.kind == "use_item" and change.item not in state.inventory: issues.append(f"{change.item} not in inventory") if change.kind == "location" and change.to not in state.adjacent_locs: issues.append(f"non-adjacent move {state.location}->{change.to}") return issues # caller re-prompts on issues ``` ### Memory-augmented retrieval (Smallville-style) ```python def retrieve_relevant(query, memory_db, k=5): """Score = recency + importance + relevance (cosine).""" now = time.time() scored = [] for m in memory_db: recency = 0.99 ** ((now - m.t) / 3600) relevance = cosine(embed(query), m.embedding) score = recency + m.importance + relevance scored.append((score, m)) return [m for _, m in sorted(scored, reverse=True)[:k]] ``` ### Branching narrative (interactive fiction) ```python def turn(state, player_input): candidates = generate_n_continuations(state, player_input, n=3) chosen = drama_manager.pick(candidates, state.arc_position) state = apply(state, chosen) state.history.append(chosen) return state, chosen.text ``` ### Constrained generation w/ JSON schema ```python schema = {"type": "object", "properties": { "narration": {"type": "string"}, "state_changes": {"type": "array", "items": {...}}, "tension_delta": {"type": "number", "minimum": -1, "maximum": 1}, }, "required": ["narration", "state_changes"]} # Use response_format=json_schema with Claude / GPT-5 ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Short interactive story | Pure LLM w/ state in prompt | | Long campaign (RPG) | LLM + structured world DB + retrieval | | Strong authorial intent | Planner + LLM surface text | | Emergent simulation | Agent-based (Smallville pattern) | | Branching narrative game | Drama manager + tree-of-beats | **기본값**: LLM beat-generator + structured world state + drama manager + retrieval memory. ## 🔗 Graph - 부모: [[Computational-Narrative]] · [[Generative-AI]] - 변형: [[Interactive-Fiction]] · [[Drama-Management]] - Adjacent: [[Large-Language-Models]] · [[Planning]] ## 🤖 LLM 활용 **언제**: games (RPG, IF), creative writing tools, simulation, training data for narrative tasks. **언제 X**: factual reporting, deterministic content (ads/legal), regulated medical/legal narration. ## ❌ 안티패턴 - **Pure LLM, no state**: forgets at chapter 3, introduces dead characters. - **Planner-only, no LLM**: prose feels mechanical. - **No drama curve**: flat tension → boring. - **Unbounded creativity**: LLM invents items/locations with no consistency check. - **Single-shot 100k-token story**: better as iterative beats with state. ## 🧪 검증 / 중복 - Verified (Park et al 2023 Generative Agents UIST, Mateas & Stern 2005, Riedl & Bulitko 2013 survey). - 신뢰도 A (theory) / B (rapidly evolving practice). ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — full PNG history + 2026 hybrid LLM/agent stack |