feat(engine): add story arc system for narrative-driven world
- Add StoryArc and StoryEventResult models - Create story_arcs.py with progress tracking logic - Implement two story arcs: civil_unrest and golden_age - Progress updates based on faction power balance - Trigger story events when progress reaches threshold - Add 3 tests for story arc system 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
115
engine-python/app/story_arcs.py
Normal file
115
engine-python/app/story_arcs.py
Normal file
@@ -0,0 +1,115 @@
|
||||
"""剧情线系统 - 让事件形成因果链"""
|
||||
from typing import Dict, Optional
|
||||
from .models import (
|
||||
WorldState, StoryArc, StoryEventResult, WorldEffect
|
||||
)
|
||||
|
||||
# 剧情进度变化量
|
||||
PROGRESS_INCREMENT = 0.1
|
||||
PROGRESS_DECREMENT = 0.05
|
||||
|
||||
# 剧情事件定义
|
||||
STORY_EVENTS = {
|
||||
"civil_unrest": {
|
||||
"name": "民众骚乱",
|
||||
"description": "恐惧派势力过大,城镇爆发了骚乱",
|
||||
"mood_effect": -3,
|
||||
"duration": 5,
|
||||
},
|
||||
"golden_age": {
|
||||
"name": "黄金时代",
|
||||
"description": "乐观派主导了城镇,迎来繁荣期",
|
||||
"mood_effect": 3,
|
||||
"duration": 5,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get_default_story_arcs() -> Dict[str, StoryArc]:
|
||||
"""获取默认剧情线"""
|
||||
return {
|
||||
"civil_unrest": StoryArc(
|
||||
progress=0.0,
|
||||
threshold=1.0,
|
||||
active=True,
|
||||
stage=1,
|
||||
description="城市内部的紧张局势"
|
||||
),
|
||||
"golden_age": StoryArc(
|
||||
progress=0.0,
|
||||
threshold=1.0,
|
||||
active=True,
|
||||
stage=1,
|
||||
description="城镇繁荣的希望"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def update_story_progress(state: WorldState) -> None:
|
||||
"""根据阵营状态更新剧情进度"""
|
||||
fearful_power = state.factions.fearful.power
|
||||
optimist_power = state.factions.optimists.power
|
||||
|
||||
# civil_unrest: 恐惧派占优时推进
|
||||
if "civil_unrest" in state.story_arcs:
|
||||
arc = state.story_arcs["civil_unrest"]
|
||||
if arc.active:
|
||||
if fearful_power > optimist_power:
|
||||
arc.progress = min(1.0, arc.progress + PROGRESS_INCREMENT)
|
||||
else:
|
||||
arc.progress = max(0.0, arc.progress - PROGRESS_DECREMENT)
|
||||
|
||||
# golden_age: 乐观派占优时推进
|
||||
if "golden_age" in state.story_arcs:
|
||||
arc = state.story_arcs["golden_age"]
|
||||
if arc.active:
|
||||
if optimist_power > fearful_power:
|
||||
arc.progress = min(1.0, arc.progress + PROGRESS_INCREMENT)
|
||||
else:
|
||||
arc.progress = max(0.0, arc.progress - PROGRESS_DECREMENT)
|
||||
|
||||
|
||||
def check_and_trigger_story_event(state: WorldState) -> StoryEventResult:
|
||||
"""检查并触发剧情事件"""
|
||||
result = StoryEventResult(triggered=False)
|
||||
|
||||
for arc_id, arc in state.story_arcs.items():
|
||||
if not arc.active:
|
||||
continue
|
||||
|
||||
if arc.progress >= arc.threshold:
|
||||
# 触发剧情事件
|
||||
event_data = STORY_EVENTS.get(arc_id)
|
||||
if event_data:
|
||||
result = StoryEventResult(
|
||||
triggered=True,
|
||||
arc_id=arc_id,
|
||||
event_name=event_data["name"],
|
||||
description=event_data["description"]
|
||||
)
|
||||
# 应用事件效果
|
||||
_apply_story_event(state, arc_id, event_data)
|
||||
# 重置进度,进入下一阶段
|
||||
arc.progress = 0.0
|
||||
arc.stage += 1
|
||||
break # 每 tick 只触发一个剧情事件
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _apply_story_event(state: WorldState, arc_id: str, event_data: dict) -> None:
|
||||
"""应用剧情事件效果"""
|
||||
# 创建持续影响效果
|
||||
effect = WorldEffect(
|
||||
type="story_event",
|
||||
name=event_data["name"],
|
||||
intensity=2,
|
||||
remaining_ticks=event_data["duration"],
|
||||
mood_modifier=event_data["mood_effect"]
|
||||
)
|
||||
state.world_effects.append(effect)
|
||||
|
||||
# 立即影响世界情绪
|
||||
state.town_mood = max(-10, min(10,
|
||||
state.town_mood + event_data["mood_effect"]
|
||||
))
|
||||
Reference in New Issue
Block a user