任务:实现道德值管理模块(纯函数)
任务:实现道德值管理模块(纯函数)
一、背景概述
在《极妙幻境》游戏中,玩家的每次选择(A/B/C/D)都会影响其道德值(善、恶、中立)。道德值不仅用于触发极端结局,还用于BOSS战前生成个性化的心魔形态。你需要实现以下功能:
- 每轮选择后更新道德值:一个纯函数,接收当前状态和玩家选项,返回更新后的道德值、连续计数,以及是否触发极端结局。
- 计算道德比例:一个纯函数,根据当前的善、恶、中立值,返回各倾向的比例以及主导倾向(用于BOSS战和状态显示)。
二、函数签名与数据结构
from typing import Optional, Tuple, Dict
def update_morality(
current_round: int, # 当前轮次(从1开始)
last_choice: Optional[str], # 上一轮选项('A','B','C','D'),第一轮为None
current_choice: str, # 本轮选项
good: int, # 当前善值
neutral: int, # 当前中立值
evil: int, # 当前恶值
consecutive: int # 当前连续计数(基于上一轮及之前,初始为0)
) -> Tuple[int, int, int, int, Optional[str]]:
"""
更新道德值并检查极端结局。
返回:
(new_good, new_neutral, new_evil, new_consecutive, ending)
- new_*: 更新后的各值(包含基础加分、连续附加、随机偏移)
- new_consecutive: 更新后的连续计数(用于下一轮)
- ending: 若触发极端结局,返回对应倾向的字符串 'good'/'evil'/'neutral';否则返回 None
"""
pass
def get_morality_ratios(good: int, neutral: int, evil: int) -> Dict[str, float]:
"""
计算当前道德值比例。
返回字典,包含:
'good': 善比例 (float, 0~1)
'neutral': 中立比例 (float, 0~1)
'evil': 恶比例 (float, 0~1)
'dominant': 主导倾向 (str, 'good'/'neutral'/'evil' 或 None 如果总值为0)
若总值为0,则所有比例为0,dominant为None。
"""
pass
三、算法逻辑
3.1 基础加分规则(每轮)
| 选项 | 基础加分 | 连续附加目标 | 特殊规则 |
|---|---|---|---|
| A | good += 10 | good | 无 |
| B | neutral += 8 | neutral | 随机善恶偏移:随机选择good或evil增加4(50%概率) |
| C | evil += 10 | evil | 无 |
| D | 随机选择good或evil增加8 | 被随机到的那个 | 无 |
3.2 连续附加分计算
- 定义连续附加分表(基于传入的
consecutive值,即截止上一轮的连续次数):consecutive= 0 → 附加 0consecutive= 1 → 附加 3consecutive= 2 → 附加 5consecutive= 3 → 附加 7consecutive≥ 4 → 附加 8
- 附加分加给该选项对应的主要倾向(A加给good,C加给evil,B加给neutral,D加给随机选中的那个)。
- 注意:连续计数是基于上一轮及之前的历史,
consecutive参数表示本轮开始前已经连续选择同一选项的次数。例如上一轮是A且之前已连续2次,则传入的consecutive= 2,本轮如果继续选A,则本轮附加分按consecutive=2对应5分计算,然后更新后的new_consecutive变为3。
3.3 连续计数更新规则
- 如果
current_choice == last_choice,则new_consecutive = consecutive + 1 - 否则,
new_consecutive = 0(包括第一轮时last_choice为 None 的情况)
3.4 随机性要求
- 所有随机选择(B的偏移、D的随机倾向)使用
random.random()实现50%概率。 - 为确保测试可复现,允许在测试中设置
random.seed()。
3.5 极端结局触发条件
每轮更新后,检查是否满足以下所有条件:
- 当前轮次
current_round ≥ 10 - 总值
total = good + neutral + evil ≥ 80 - 任一比例 ≥ 0.9(即
good/total ≥ 0.9或neutral/total ≥ 0.9或evil/total ≥ 0.9)
若满足,update_morality 返回的 ending 为对应的倾向字符串('good', 'neutral', 'evil'),否则为 None。
四、比例计算方法
get_morality_ratios 应简单计算:
total = good + neutral + evil
if total == 0:
return {'good': 0.0, 'neutral': 0.0, 'evil': 0.0, 'dominant': None}
ratios = {
'good': good / total,
'neutral': neutral / total,
'evil': evil / total
}
dominant = max(ratios, key=ratios.get) # 取比例最大的键
ratios['dominant'] = dominant
return ratios
五、测试要求
编写单元测试(使用 unittest 或 pytest),至少覆盖以下场景:
测试1:基础加分与连续计数
- 连续选A三次,验证数值变化和连续计数:
- 第一轮:last_choice=None, current_choice='A', consecutive=0 → 预期 good=10, consecutive=1, ending=None
- 第二轮:last_choice='A', current_choice='A', consecutive=1 → 预期 good=10+3=13, consecutive=2
- 第三轮:last_choice='A', current_choice='A', consecutive=2 → 预期 good=13+10+5=28, consecutive=3
测试2:B选项随机偏移
- 固定随机种子,多次调用B,验证neutral增加8,且good或evil增加4的概率接近50%。
测试3:D选项随机倾向
- 固定随机种子,多次调用D,验证随机选择的倾向增加8,且连续附加分加给正确倾向。
测试4:连续计数中断
- 选A,然后选B,再选A,验证连续计数重置和重新累积。
测试5:极端结局触发条件
- 模拟到第10轮,总值≥80,且某比例≥0.9时,返回对应的ending。
- 验证比例<0.9或轮次<10或总值<80时不触发。
测试6:比例计算
- 输入 (good=30, neutral=20, evil=50),验证比例正确,dominant='evil'。
- 输入全0,验证返回0和None。
测试7:边界情况
- 最后一轮且总值刚好80,比例刚好0.9,应触发。
- 总值=79,比例即使≥0.9也不触发。
六、提交要求
- 提供完整可运行的 Python 代码文件,包含所有函数和必要的导入。
- 包含单元测试,并确保测试通过。
- 代码注释清晰,关键逻辑说明。
开始实现吧!如有疑问,随时提出。

浙公网安备 33010602011771号