任务:实现道德值管理模块(纯函数)

任务:实现道德值管理模块(纯函数)

一、背景概述

在《极妙幻境》游戏中,玩家的每次选择(A/B/C/D)都会影响其道德值(善、恶、中立)。道德值不仅用于触发极端结局,还用于BOSS战前生成个性化的心魔形态。你需要实现以下功能:

  1. 每轮选择后更新道德值:一个纯函数,接收当前状态和玩家选项,返回更新后的道德值、连续计数,以及是否触发极端结局。
  2. 计算道德比例:一个纯函数,根据当前的善、恶、中立值,返回各倾向的比例以及主导倾向(用于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 → 附加 0
    • consecutive = 1 → 附加 3
    • consecutive = 2 → 附加 5
    • consecutive = 3 → 附加 7
    • consecutive ≥ 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 极端结局触发条件

每轮更新后,检查是否满足以下所有条件

  1. 当前轮次 current_round ≥ 10
  2. 总值 total = good + neutral + evil ≥ 80
  3. 任一比例 ≥ 0.9(即 good/total ≥ 0.9neutral/total ≥ 0.9evil/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

五、测试要求

编写单元测试(使用 unittestpytest),至少覆盖以下场景:

测试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 代码文件,包含所有函数和必要的导入。
  • 包含单元测试,并确保测试通过。
  • 代码注释清晰,关键逻辑说明。

开始实现吧!如有疑问,随时提出。

posted @ 2026-03-15 20:27  神秘园欢迎您  阅读(13)  评论(0)    收藏  举报