Files
cultivation-world-simulator/src/classes/action/battle.py
2025-10-16 00:54:34 +08:00

69 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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]