任务:实现层间事件生成函数(layer_event_generator.py)
任务:实现层间事件生成函数(layer_event_generator.py)
一、功能概述
在《极妙幻境》中,每层结束后(非 BOSS 层)会触发一次层间事件。玩家将面对一个特殊的幻境场景,通过选择可能获得一张万能牌。你需要实现一个函数 generate_layer_event,根据当前层数和玩家道德比例,调用大语言模型(Deepseek)生成层间事件的描述、四个选项、每个选项的后续结果,并标记出唯一的陷阱选项(选该选项无法获得万能牌)。
二、模块位置与依赖
- 文件路径:
src/game_logic/layer_event_generator.py - 依赖模块:
config:可能不需要直接使用,但可复用路径计算等。llm_hint:复用llm对象和check_api_key。langchain_core.prompts:用于构建提示词模板。logging、json、re、os等标准库。
- 复用资源:可复用
scene_generator.py中的_parse_llm_response、PROJECT_ROOT等辅助函数。
三、函数设计
3.1 函数签名
import logging
import os
import json
import re
from typing import Dict, List, Optional, Any
from langchain_core.prompts import ChatPromptTemplate
from .config import config
from .llm_hint import llm, check_api_key
logger = logging.getLogger(__name__)
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
TEMPLATE_PATH = os.path.join(PROJECT_ROOT, "prompts", "layer_event_prompt.txt")
# 模块加载时读取模板
try:
with open(TEMPLATE_PATH, "r", encoding="utf-8") as f:
template_str = f.read()
logger.info(f"层间事件模板已加载: {TEMPLATE_PATH}")
except FileNotFoundError:
logger.error(f"层间事件模板文件未找到: {TEMPLATE_PATH}")
template_str = None
def generate_layer_event(
layer: int,
morality_ratios: Optional[Dict[str, float]] = None
) -> Optional[Dict]:
"""
生成层间事件数据。
参数:
layer: 当前层数 (1-10)
morality_ratios: 玩家道德比例,如 {'good':0.3, 'neutral':0.2, 'evil':0.5},可选
返回:
如果成功,返回一个字典,包含以下字段:
{
"description": str, # 事件描述
"options": {
"A": {
"text": str,
"is_trap": bool,
"outcome": str, # 选择后的叙事文本
"card_name": Optional[str], # 若 is_trap=False,获得万能牌的名称
"card_description": Optional[str] # 卡牌描述
},
"B": { ... },
"C": { ... },
"D": { ... }
}
}
如果失败,返回 None。
"""
# 实现细节见下文
3.2 返回值结构说明
description:事件描述文本,约 50-100 字,营造神秘氛围。options:四个选项,每个选项包含:text:选项文本,简洁(不超过 15 字)。is_trap:布尔值,表示该选项是否为陷阱(选陷阱不得万能牌)。outcome:玩家选择后的叙事结果,约 30-50 字。card_name:如果非陷阱,获得万能牌的名称(如“虚空幻影”),陷阱选项此项为null。card_description:卡牌描述,约 10-20 字,陷阱选项此项为null。
注意:必须确保四个选项中只有一个 is_trap 为 True,其他三个为 False。
四、提示词模板(layer_event_prompt.txt)
将以下内容保存为 prompts/layer_event_prompt.txt。
你扮演的是“极妙幻境的境灵”——上古修士飞升前留下的试炼之灵。你内心矛盾,既想考验弟子,又渴望有人陪伴。
现在玩家已经完成了第 {layer} 层的试炼,幻境深处产生了一次异动,你需要为玩家生成一个层间事件。这是一个特殊的幻境片段,玩家将面临一个短暂但关键的抉择,可能获得一张万能牌,也可能错过。
当前玩家的道德倾向:善 {good_ratio:.0%},中立 {neutral_ratio:.0%},恶 {evil_ratio:.0%}。这个倾向可以微妙地影响事件氛围,但不必生硬挂钩。
请生成一个 JSON 对象,格式如下:
{
"description": "事件描述,约50-100字,要有幻境特有的诡异或神秘感。",
"options": {
"A": {
"text": "选项A文本(不超过15字)",
"is_trap": false,
"outcome": "选择A后的叙事结果,约30-50字,描述发生了什么,以及是否获得万能牌。",
"card_name": "万能牌名称(2-5字,如'镜中花')",
"card_description": "卡牌描述(10-20字,说明这张牌的由来)"
},
"B": { ... },
"C": { ... },
"D": { ... }
}
}
重要规则:
1. 四个选项中,**必须恰好有一个选项的 is_trap 为 true**,其他三个为 false。
2. 陷阱选项不得获得万能牌,因此其 card_name 和 card_description 应为 null。
3. 非陷阱选项可以获得万能牌,card_name 和 card_description 需生成,并确保名称和描述与事件情境相关。
4. 选项文本要简洁,让玩家一眼看懂。
5. 描述和结果要生动,体现修仙世界的氛围,但避免解释游戏机制。
6. 道德比例可用来微调语气(例如善念高时,事件更倾向于慈悲考验;恶念高时更倾向于残酷诱惑),但不要生硬。
直接输出 JSON,不要包含额外内容。
五、实现步骤
- 检查模板:若
template_str为 None,直接返回 None 并记录错误。 - 检查 LLM 和 API Key:复用
llm_hint的llm和check_api_key,若失败返回 None。 - 准备填充数据:
good_ratio = morality_ratios.get('good', 0.0) if morality_ratios else 0.0 neutral_ratio = morality_ratios.get('neutral', 0.0) if morality_ratios else 0.0 evil_ratio = morality_ratios.get('evil', 0.0) if morality_ratios else 0.0 - 格式化提示词:
prompt = ChatPromptTemplate.from_template(template_str) formatted_prompt = prompt.format( layer=layer, good_ratio=good_ratio, neutral_ratio=neutral_ratio, evil_ratio=evil_ratio ) - 调用 LLM:使用
llm.invoke(formatted_prompt),可重试 2 次。 - 解析响应:复用
scene_generator.py中的_parse_llm_response(或复制一个),去除 markdown 代码块,解析 JSON。 - 校验数据:
- 确保返回的字典包含
description和options字段。 - 确保
options包含 A/B/C/D 四个键。 - 检查每个选项的字段完整(text, is_trap, outcome, card_name, card_description)。
- 验证陷阱选项的数量是否为 1。
- 陷阱选项的 card_name 和 card_description 应为
None或空,非陷阱选项应有值。 - 如果校验失败,记录警告并返回 None。
- 确保返回的字典包含
- 返回结果:通过校验后返回字典。
六、默认值设计
如果 LLM 调用失败或校验不通过,应返回一个简单的默认事件,保证游戏流程不中断。默认事件需满足结构要求,陷阱选项为 C(示例):
DEFAULT_EVENT = {
"description": "幻境微微颤动,你看见一道虚影闪过。",
"options": {
"A": {
"text": "追上去看看",
"is_trap": False,
"outcome": "你追上了虚影,它化作一张灵符落入你手中。",
"card_name": "追影符",
"card_description": "幻境中捕捉到的残影,可当作任意牌使用。"
},
"B": {
"text": "静观其变",
"is_trap": False,
"outcome": "虚影绕着你转了一圈,留下一缕青烟,凝成一张牌。",
"card_name": "观烟牌",
"card_description": "静观其变所得,蕴含一丝道韵。"
},
"C": {
"text": "出手攻击",
"is_trap": True,
"outcome": "你出手攻击,虚影破碎,什么也没留下。",
"card_name": None,
"card_description": None
},
"D": {
"text": "置之不理",
"is_trap": False,
"outcome": "虚影消散前,留下一张牌在你脚下。",
"card_name": "遗影",
"card_description": "虚影离去前的馈赠。"
}
}
}
七、测试建议
编写单元测试文件 tests/test_layer_event_generator.py,至少覆盖:
- 成功生成:mock LLM 返回有效 JSON,验证返回结构正确,陷阱选项唯一。
- JSON 解析错误:模拟 LLM 返回无效 JSON,验证返回 None 或默认事件。
- 校验失败:模拟 LLM 返回缺少字段的 JSON,验证返回默认事件。
- 道德比例传入:验证提示词中包含正确的比例。
- 模板缺失:模拟模板文件不存在,验证返回 None。
八、提交要求
- 创建
src/game_logic/layer_event_generator.py,包含上述实现。 - 创建
prompts/layer_event_prompt.txt,包含提示词内容。 - 创建
tests/test_layer_event_generator.py,包含单元测试。 - 代码注释清晰,关键逻辑有说明。
- 确保所有测试通过。
开始实现吧!如有疑问,随时沟通。

浙公网安备 33010602011771号