refactor tribulation
This commit is contained in:
@@ -6,28 +6,16 @@ from src.classes.action.cooldown import cooldown_action
|
||||
from src.classes.event import Event
|
||||
from src.classes.cultivation import Realm
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.relation import Relation
|
||||
from src.classes.tribulation import TribulationSelector
|
||||
from src.classes.hp_and_mp import HP_MAX_BY_REALM, MP_MAX_BY_REALM
|
||||
from src.classes.effect import _merge_effects
|
||||
|
||||
# —— 配置:哪些“出发境界”会生成突破小故事(global var)——
|
||||
# —— 配置:哪些"出发境界"会生成突破小故事(global var)——
|
||||
ALLOW_STORY_FROM_REALMS: list[Realm] = [
|
||||
Realm.Foundation_Establishment, # 筑基
|
||||
Realm.Core_Formation, # 金丹
|
||||
]
|
||||
|
||||
# 故事提示词(global var)
|
||||
STORY_PROMPT_BASE = "以古风、凝练、不炫技的笔触,描绘修士历经{calamity}劫时的心境与取舍,篇幅60~120字。"
|
||||
|
||||
# 劫难说明(global var)
|
||||
CALAMITY_DESCRIPTIONS: dict[str, str] = {
|
||||
"心魔": "心念起伏,自我否定与执念缠斗,外寂而内喧。",
|
||||
"雷劫": "天威如潮,电光凝成纹理,压迫骨血与神识。",
|
||||
"肉身": "筋骨皮膜重塑,真气磨砺经脉,疼痛与新生并至。",
|
||||
"寻仇": "仇人旧怨不散,刀光在心底回响,一念之差改写因果。",
|
||||
"情劫": "柔情即刃,难舍难分,念头被拉回人间烟火。",
|
||||
}
|
||||
from src.classes.hp_and_mp import HP_MAX_BY_REALM, MP_MAX_BY_REALM
|
||||
from src.classes.effect import _merge_effects
|
||||
|
||||
|
||||
@cooldown_action
|
||||
class Breakthrough(TimedAction):
|
||||
@@ -120,8 +108,8 @@ class Breakthrough(TimedAction):
|
||||
# 仅基于出发境界判断是否生成故事
|
||||
self._gen_story = old_realm in ALLOW_STORY_FROM_REALMS
|
||||
if self._gen_story:
|
||||
self._calamity = self._choose_calamity()
|
||||
self._calamity_other = self._choose_related_avatar(self._calamity)
|
||||
self._calamity = TribulationSelector.choose_tribulation(self.avatar)
|
||||
self._calamity_other = TribulationSelector.choose_related_avatar(self.avatar, self._calamity)
|
||||
else:
|
||||
self._calamity = None
|
||||
self._calamity_other = None
|
||||
@@ -152,31 +140,9 @@ class Breakthrough(TimedAction):
|
||||
|
||||
if True:
|
||||
# 故事参与者:本体 +(可选)相关角色
|
||||
desc = CALAMITY_DESCRIPTIONS.get(str(calamity), "")
|
||||
prompt = (STORY_PROMPT_BASE.format(calamity=str(calamity)) + (" " + desc if desc else "")).strip()
|
||||
prompt = TribulationSelector.get_story_prompt(str(calamity))
|
||||
story = StoryTeller.tell_from_actors(core_text, ("突破成功" if result_ok else "突破失败"), self.avatar, getattr(self, "_calamity_other", None), prompt=prompt)
|
||||
events.append(Event(self.world.month_stamp, story, related_avatars=rel_ids))
|
||||
return events
|
||||
|
||||
# ——— 内部:劫难选择与关联角色 ———
|
||||
def _choose_calamity(self) -> str:
|
||||
base = ["心魔", "雷劫", "肉身"]
|
||||
rels = getattr(self.avatar, "relations", {})
|
||||
has_enemy = any(rel is Relation.ENEMY for rel in rels.values())
|
||||
has_lover = any(rel is Relation.LOVERS for rel in rels.values())
|
||||
if has_enemy:
|
||||
base.append("寻仇")
|
||||
if has_lover:
|
||||
base.append("情劫")
|
||||
return random.choice(base)
|
||||
|
||||
def _choose_related_avatar(self, calamity: str):
|
||||
if calamity not in ("寻仇", "情劫"):
|
||||
return None
|
||||
target_rel = Relation.ENEMY if calamity == "寻仇" else Relation.LOVERS
|
||||
candidates = [other for other, rel in self.avatar.relations.items() if rel is target_rel]
|
||||
if not candidates:
|
||||
return None
|
||||
return random.choice(candidates)
|
||||
|
||||
|
||||
|
||||
172
src/classes/tribulation.py
Normal file
172
src/classes/tribulation.py
Normal file
@@ -0,0 +1,172 @@
|
||||
"""
|
||||
天劫系统
|
||||
负责管理突破时的各种劫难类型、描述和选择逻辑
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import random
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
from src.classes.relation import Relation
|
||||
|
||||
|
||||
@dataclass
|
||||
class TribulationType:
|
||||
"""天劫类型定义"""
|
||||
name: str # 劫难名称
|
||||
description: str # 劫难描述(用于生成故事的提示)
|
||||
requires_other_avatar: bool = False # 是否需要关联其他角色
|
||||
relation_type: Optional[Relation] = None # 需要的关系类型
|
||||
|
||||
|
||||
# 天劫类型定义
|
||||
TRIBULATION_TYPES = {
|
||||
"心魔": TribulationType(
|
||||
name="心魔",
|
||||
description="心念起伏,自我否定与执念缠斗,外寂而内喧。道心深处,旧日疑惑与未来迷茫交织,一念之差即可坠入心魔深渊。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"雷劫": TribulationType(
|
||||
name="雷劫",
|
||||
description="天威如潮,电光凝成纹理,压迫骨血与神识。紫霄雷霆自九天垂落,每一道雷光都是天地对修士的考校,稍有不慎便是形神俱灭。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"肉身": TribulationType(
|
||||
name="肉身",
|
||||
description="筋骨皮膜重塑,真气磨砺经脉,疼痛与新生并至。肉身如熔炉,每一寸血肉都在烈火中淬炼,破而后立,痛极方能重生。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"寻仇": TribulationType(
|
||||
name="寻仇",
|
||||
description="仇人旧怨不散,刀光在心底回响,一念之差改写因果。因果纠缠,宿怨难消,突破之际正是因果清算之时。",
|
||||
requires_other_avatar=True,
|
||||
relation_type=Relation.ENEMY
|
||||
),
|
||||
"情劫": TribulationType(
|
||||
name="情劫",
|
||||
description="柔情即刃,难舍难分,念头被拉回人间烟火。情丝缠绕,斩不断理还乱,一念执着便是万劫不复。",
|
||||
requires_other_avatar=True,
|
||||
relation_type=Relation.LOVERS
|
||||
),
|
||||
"阳罡": TribulationType(
|
||||
name="阳罡",
|
||||
description="日轮灼烈,天地赤白两色,阳罡刀风如白金烈焰。正气涤秽,刚猛直击,阳盛则裂。午时最烈,光杀心识,经脉燥爆之险时刻相随。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"雷火": TribulationType(
|
||||
name="雷火",
|
||||
description="云海层叠,紫电潜伏,雷中生火、火中孕雷。外冲与内炼同调,神魂与经络双线考校。雷海覆顶,业劫天火焚因果,一瞬之间便是生死两重天。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"风灾": TribulationType(
|
||||
name="风灾",
|
||||
description="无风之地先起丝音,罡风断骨,真空撕扯,噬灵风蚀。风洞共鸣如锯切,位移与姿态稍有不慎便是肉身裂口、护体法相被剥。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"阴狱": TribulationType(
|
||||
name="阴狱",
|
||||
description="温度突降,黑霜上爬,冤魂压境,寒狱锁身。六道幻刑,阴火烛骨,以业、怖、悔、执为四柱。善恶因果入场,心神判定重于肉身。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
"魔劫": TribulationType(
|
||||
name="魔劫",
|
||||
description="心跳与灵识节奏错位,旧欲旧恨自启,识海生魔胎影。心魔境中,欲、嗔、痴、慢、疑轮番试探,道心完整度与自洽度为核,一念之差即可走火入魔。",
|
||||
requires_other_avatar=False
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
# 故事生成的基础提示词
|
||||
STORY_PROMPT_BASE = "以古风、凝练、不炫技的笔触,描绘修士历经{calamity}劫时的心境与取舍,篇幅100~150字。"
|
||||
|
||||
|
||||
class TribulationSelector:
|
||||
"""天劫选择器,负责根据修士状态选择合适的劫难"""
|
||||
|
||||
@staticmethod
|
||||
def choose_tribulation(avatar: Avatar) -> str:
|
||||
"""
|
||||
根据修士的境界、关系等选择劫难类型
|
||||
|
||||
Args:
|
||||
avatar: 渡劫的修士
|
||||
|
||||
Returns:
|
||||
劫难名称
|
||||
"""
|
||||
# 基础劫难池(不需要其他角色)
|
||||
base_tribulations = ["心魔", "雷劫", "肉身", "阳罡", "雷火", "风灾", "阴狱", "魔劫"]
|
||||
|
||||
# 检查是否有特殊关系,可以触发关系型劫难
|
||||
available_tribulations = base_tribulations.copy()
|
||||
|
||||
rels = getattr(avatar, "relations", {})
|
||||
has_enemy = any(rel is Relation.ENEMY for rel in rels.values())
|
||||
has_lover = any(rel is Relation.LOVERS for rel in rels.values())
|
||||
|
||||
if has_enemy:
|
||||
available_tribulations.append("寻仇")
|
||||
if has_lover:
|
||||
available_tribulations.append("情劫")
|
||||
|
||||
return random.choice(available_tribulations)
|
||||
|
||||
@staticmethod
|
||||
def choose_related_avatar(avatar: Avatar, tribulation_name: str) -> Optional[Avatar]:
|
||||
"""
|
||||
根据劫难类型选择相关的角色(如果需要)
|
||||
|
||||
Args:
|
||||
avatar: 渡劫的修士
|
||||
tribulation_name: 劫难名称
|
||||
|
||||
Returns:
|
||||
相关角色,如果不需要则返回 None
|
||||
"""
|
||||
tribulation = TRIBULATION_TYPES.get(tribulation_name)
|
||||
if not tribulation or not tribulation.requires_other_avatar:
|
||||
return None
|
||||
|
||||
target_rel = tribulation.relation_type
|
||||
candidates = [
|
||||
other for other, rel in avatar.relations.items()
|
||||
if rel is target_rel
|
||||
]
|
||||
|
||||
if not candidates:
|
||||
return None
|
||||
|
||||
return random.choice(candidates)
|
||||
|
||||
@staticmethod
|
||||
def get_description(tribulation_name: str) -> str:
|
||||
"""
|
||||
获取劫难的描述文本
|
||||
|
||||
Args:
|
||||
tribulation_name: 劫难名称
|
||||
|
||||
Returns:
|
||||
劫难描述
|
||||
"""
|
||||
tribulation = TRIBULATION_TYPES.get(tribulation_name)
|
||||
return tribulation.description if tribulation else ""
|
||||
|
||||
@staticmethod
|
||||
def get_story_prompt(tribulation_name: str) -> str:
|
||||
"""
|
||||
获取生成故事的提示词
|
||||
|
||||
Args:
|
||||
tribulation_name: 劫难名称
|
||||
|
||||
Returns:
|
||||
完整的故事生成提示词
|
||||
"""
|
||||
desc = TribulationSelector.get_description(tribulation_name)
|
||||
prompt = STORY_PROMPT_BASE.format(calamity=tribulation_name)
|
||||
return (prompt + (" " + desc if desc else "")).strip()
|
||||
|
||||
Reference in New Issue
Block a user