add long time memory
This commit is contained in:
@@ -126,7 +126,34 @@ class ActualActionMixin():
|
||||
不一定是多个step,也有可能就一个step。
|
||||
|
||||
新接口:子类必须实现 can_start/start/step/finish。
|
||||
|
||||
类变量:
|
||||
- IS_MAJOR: 是否为大事(长期记忆),默认False(小事/短期记忆)
|
||||
"""
|
||||
|
||||
# 默认为小事(短期记忆)
|
||||
IS_MAJOR: bool = False
|
||||
|
||||
def create_event(self, content: str, related_avatars=None) -> Event:
|
||||
"""
|
||||
创建事件的辅助方法,自动带上is_major属性
|
||||
|
||||
Args:
|
||||
content: 事件内容
|
||||
related_avatars: 相关角色ID列表
|
||||
|
||||
Returns:
|
||||
Event对象,is_major根据当前Action的IS_MAJOR类变量设置
|
||||
"""
|
||||
from src.classes.action.action import Action
|
||||
# 获取当前类的IS_MAJOR属性
|
||||
is_major = self.__class__.IS_MAJOR if hasattr(self.__class__, 'IS_MAJOR') else False
|
||||
return Event(
|
||||
month_stamp=self.world.month_stamp,
|
||||
content=content,
|
||||
related_avatars=related_avatars,
|
||||
is_major=is_major
|
||||
)
|
||||
|
||||
@abstractmethod
|
||||
def can_start(self, **params) -> tuple[bool, str]:
|
||||
@@ -164,7 +191,7 @@ class TimedAction(DefineAction, ActualActionMixin):
|
||||
duration_months: int = 1
|
||||
|
||||
def step(self, **params) -> ActionResult:
|
||||
if getattr(self, 'start_monthstamp', None) is None:
|
||||
if not hasattr(self, 'start_monthstamp') or self.start_monthstamp is None:
|
||||
self.start_monthstamp = self.world.month_stamp
|
||||
self._execute(**params)
|
||||
done = (self.world.month_stamp - self.start_monthstamp) >= (self.duration_months - 1)
|
||||
|
||||
@@ -15,6 +15,8 @@ class Battle(InstantAction):
|
||||
STORY_PROMPT: str | None = (
|
||||
"不要出现具体血量、伤害点数或任何数值表达。"
|
||||
)
|
||||
# 战斗是大事(长期记忆)
|
||||
IS_MAJOR: bool = True
|
||||
|
||||
def _get_target(self, avatar_name: str):
|
||||
"""
|
||||
@@ -62,7 +64,7 @@ class Battle(InstantAction):
|
||||
rel_ids.append(target.id)
|
||||
except Exception:
|
||||
pass
|
||||
event = Event(self.world.month_stamp, f"{self.avatar.name} 对 {target_name} 发起战斗(战斗力:{self.avatar.name} {int(s_att)} vs {target_name} {int(s_def)})", related_avatars=rel_ids)
|
||||
event = Event(self.world.month_stamp, f"{self.avatar.name} 对 {target_name} 发起战斗(战斗力:{self.avatar.name} {int(s_att)} vs {target_name} {int(s_def)})", related_avatars=rel_ids, is_major=True)
|
||||
# 记录开始事件内容,供故事生成使用
|
||||
self._start_event_content = event.content
|
||||
return event
|
||||
@@ -83,13 +85,13 @@ class Battle(InstantAction):
|
||||
rel_ids.append(t.id)
|
||||
except Exception:
|
||||
pass
|
||||
result_event = Event(self.world.month_stamp, result_text, related_avatars=rel_ids)
|
||||
result_event = Event(self.world.month_stamp, result_text, related_avatars=rel_ids, is_major=True)
|
||||
|
||||
# 生成战斗小故事(同步调用,与其他动作保持一致)
|
||||
target = self._get_target(avatar_name)
|
||||
start_text = getattr(self, "_start_event_content", "") or result_event.content
|
||||
start_text = self._start_event_content if hasattr(self, '_start_event_content') else result_event.content
|
||||
story = StoryTeller.tell_from_actors(start_text, result_event.content, self.avatar, target, prompt=self.STORY_PROMPT)
|
||||
story_event = Event(self.world.month_stamp, story, related_avatars=rel_ids)
|
||||
story_event = Event(self.world.month_stamp, story, related_avatars=rel_ids, is_story=True)
|
||||
|
||||
return [result_event, story_event]
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ class Breakthrough(TimedAction):
|
||||
PARAMS = {}
|
||||
# 冷却:突破应当有CD,避免连刷
|
||||
ACTION_CD_MONTHS: int = 3
|
||||
# 突破是大事(长期记忆)
|
||||
IS_MAJOR: bool = True
|
||||
# 保留类级常量声明,实际读取模块级配置
|
||||
|
||||
def calc_success_rate(self) -> float:
|
||||
@@ -65,8 +67,8 @@ class Breakthrough(TimedAction):
|
||||
# 记录结果用于 finish 事件
|
||||
self._last_result = (
|
||||
"success",
|
||||
getattr(old_realm, "value", str(old_realm)),
|
||||
getattr(new_realm, "value", str(new_realm)),
|
||||
old_realm.value,
|
||||
new_realm.value,
|
||||
)
|
||||
else:
|
||||
# 突破失败:减少最大寿元上限
|
||||
@@ -100,12 +102,11 @@ class Breakthrough(TimedAction):
|
||||
return (ok, "" if ok else "当前不处于瓶颈,无法突破")
|
||||
|
||||
def start(self) -> Event:
|
||||
# 清理状态
|
||||
# 初始化状态
|
||||
self._last_result = None
|
||||
self._success_rate_cached = None
|
||||
# 预判是否生成故事与选择劫难
|
||||
old_realm = self.avatar.cultivation_progress.realm
|
||||
# 仅基于出发境界判断是否生成故事
|
||||
self._gen_story = old_realm in ALLOW_STORY_FROM_REALMS
|
||||
if self._gen_story:
|
||||
self._calamity = TribulationSelector.choose_tribulation(self.avatar)
|
||||
@@ -113,36 +114,33 @@ class Breakthrough(TimedAction):
|
||||
else:
|
||||
self._calamity = None
|
||||
self._calamity_other = None
|
||||
return Event(self.world.month_stamp, f"{self.avatar.name} 开始尝试突破境界", related_avatars=[self.avatar.id])
|
||||
return Event(self.world.month_stamp, f"{self.avatar.name} 开始尝试突破境界", related_avatars=[self.avatar.id], is_major=True)
|
||||
|
||||
# TimedAction 已统一 step 逻辑
|
||||
|
||||
def finish(self) -> list[Event]:
|
||||
res = getattr(self, "_last_result", None)
|
||||
if not (isinstance(res, tuple) and res):
|
||||
if not self._last_result:
|
||||
return []
|
||||
result_ok = res[0] == "success"
|
||||
if not getattr(self, "_gen_story", False):
|
||||
result_ok = self._last_result[0] == "success"
|
||||
if not self._gen_story:
|
||||
# 不生成故事:不出现劫难,仅简单结果
|
||||
core_text = f"{self.avatar.name} 突破{'成功' if result_ok else '失败'}"
|
||||
return [Event(self.world.month_stamp, core_text, related_avatars=[self.avatar.id])]
|
||||
return [Event(self.world.month_stamp, core_text, related_avatars=[self.avatar.id], is_major=True)]
|
||||
|
||||
calamity = getattr(self, "_calamity", "劫难")
|
||||
calamity = self._calamity
|
||||
core_text = f"{self.avatar.name} 遭遇了{calamity}劫难,突破{'成功' if result_ok else '失败'}"
|
||||
rel_ids = [self.avatar.id]
|
||||
other = getattr(self, "_calamity_other", None)
|
||||
if other is not None:
|
||||
if self._calamity_other is not None:
|
||||
try:
|
||||
rel_ids.append(other.id)
|
||||
rel_ids.append(self._calamity_other.id)
|
||||
except Exception:
|
||||
pass
|
||||
events: list[Event] = [Event(self.world.month_stamp, core_text, related_avatars=rel_ids)]
|
||||
events: list[Event] = [Event(self.world.month_stamp, core_text, related_avatars=rel_ids, is_major=True)]
|
||||
|
||||
if True:
|
||||
# 故事参与者:本体 +(可选)相关角色
|
||||
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))
|
||||
# 故事参与者:本体 +(可选)相关角色
|
||||
prompt = TribulationSelector.get_story_prompt(str(calamity))
|
||||
story = StoryTeller.tell_from_actors(core_text, ("突破成功" if result_ok else "突破失败"), self.avatar, self._calamity_other, prompt=prompt)
|
||||
events.append(Event(self.world.month_stamp, story, related_avatars=rel_ids, is_story=True))
|
||||
return events
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user