from __future__ import annotations from src.classes.action import InstantAction from src.classes.event import Event from src.classes.battle import decide_battle, get_effective_strength_pair from src.classes.story_teller import StoryTeller class Battle(InstantAction): COMMENT = "与目标进行对战,判定胜负" DOABLES_REQUIREMENTS = "任何时候都可以执行" PARAMS = {"avatar_name": "AvatarName"} # 提供用于故事生成的提示词:不出现血量/伤害等数值描述 STORY_PROMPT: str | None = ( "不要出现具体血量、伤害点数或任何数值表达。" ) def _get_target(self, avatar_name: str): for v in self.world.avatar_manager.avatars.values(): if v.name == avatar_name: return v return None def _execute(self, avatar_name: str) -> None: target = self._get_target(avatar_name) if target is None: return winner, loser, loser_damage, winner_damage = decide_battle(self.avatar, target) # 应用双方伤害 loser.hp.reduce(loser_damage) winner.hp.reduce(winner_damage) self._last_result = (winner.name, loser.name, loser_damage, winner_damage) def can_start(self, avatar_name: str | None = None) -> bool: if avatar_name is None: return False return self._get_target(avatar_name) is not None def start(self, avatar_name: str) -> Event: target = self._get_target(avatar_name) target_name = target.name if target is not None else avatar_name # 展示双方折算战斗力(基于对手、含克制) s_att, s_def = get_effective_strength_pair(self.avatar, target) event = Event(self.world.month_stamp, f"{self.avatar.name} 对 {target_name} 发起战斗(战斗力:{self.avatar.name} {int(s_att)} vs {target_name} {int(s_def)})") # 记录开始事件内容,供故事生成使用 self._start_event_content = event.content return event # InstantAction 已实现 step 完成 def finish(self, avatar_name: str) -> list[Event]: res = self._last_result if not (isinstance(res, tuple) and len(res) == 4): return [] winner, loser = res[0], res[1] loser_damage, winner_damage = res[2], res[3] result_text = f"{winner} 战胜了 {loser},{loser} 受伤{loser_damage}点,{winner} 也受伤{winner_damage}点" result_event = Event(self.world.month_stamp, result_text) # 生成战斗小故事:直接复用已生成的事件文本 target = self._get_target(avatar_name) avatar_infos = StoryTeller.build_avatar_infos(self.avatar, target) start_text = getattr(self, "_start_event_content", "") or result_event.content story = StoryTeller.tell_story(avatar_infos, start_text, result_event.content, self.STORY_PROMPT) story_event = Event(self.world.month_stamp, story) return [result_event, story_event]