refactor mutual actions

This commit is contained in:
bridge
2025-10-02 18:52:13 +08:00
parent eac6a08707
commit f4ef5a00de
2 changed files with 29 additions and 31 deletions

View File

@@ -15,8 +15,6 @@ from src.classes.action import long_action
if TYPE_CHECKING:
from src.classes.avatar import Avatar
# 默认所有的互动都是1个月时间
@long_action(step_month=1)
class MutualAction(DefineAction, LLMAction):
"""
互动动作A 对 B 发起动作B 可以给出反馈(由 LLM 决策)。
@@ -64,14 +62,15 @@ class MutualAction(DefineAction, LLMAction):
"""
将反馈决定落地为目标角色的立即动作(清空后加载单步动作链)。
"""
# 抢占:清空后续计划并中断其当前动作
self._preempt_avatar(target_avatar)
# 先加载为计划
target_avatar.load_decide_result_chain([(action_name, action_params)], target_avatar.thinking, "")
# 立即提交为当前动作,触发开始事件
start_event = target_avatar.commit_next_plan()
if start_event is not None:
# 侧边栏仅推送一次(由动作发起方承担),另一侧仅写历史
self.avatar.add_event(start_event)
target_avatar.add_event(start_event, to_sidebar=False)
self._add_event_pair(start_event, initiator=self.avatar, target=target_avatar)
def _settle_feedback(self, target_avatar: "Avatar", feedback_name: str) -> None:
"""
@@ -83,21 +82,29 @@ class MutualAction(DefineAction, LLMAction):
# 默认不额外记录,由事件系统承担
return
# 通用工具:按名找人
def _find_avatar_by_name(self, name: str) -> "Avatar|None":
for v in self.world.avatar_manager.avatars.values():
if v.name == name:
return v
return None
def _get_target_avatar(self, target_avatar: "Avatar|str") -> "Avatar|None":
"""
获取目标角色,支持传入角色对象或名字字符串
Returns:
目标角色,如果找不到返回 None
"""
if isinstance(target_avatar, str):
name = target_avatar
for v in self.world.avatar_manager.avatars.values():
if v.name == name:
return v
return None
return self._find_avatar_by_name(target_avatar)
return target_avatar
# 通用工具:抢占 avatar 当前动作
def _preempt_avatar(self, avatar: "Avatar") -> None:
avatar.clear_plans()
avatar.current_action = None
# 通用工具:向两人推事件(侧栏只推 initiator
def _add_event_pair(self, event: Event, initiator: "Avatar", target: "Avatar") -> None:
initiator.add_event(event)
if target is not None:
target.add_event(event, to_sidebar=False)
def _execute(self, target_avatar: "Avatar|str") -> None:
# 允许传入名字字符串
target_avatar = self._get_target_avatar(target_avatar)
@@ -114,8 +121,7 @@ class MutualAction(DefineAction, LLMAction):
# 挂到目标的thinking上面向UI/日志),并执行反馈落地
target_avatar.thinking = thinking
# 1) 先清空目标后续计划(仅清空队列,不动当前动作)
if hasattr(target_avatar, "clear_plans"):
target_avatar.clear_plans()
target_avatar.clear_plans()
# 2) 再结算反馈映射为对应动作
self._settle_feedback(target_avatar, feedback)
# 3) 反馈事件(进入侧边栏与双方历史,中文化文案)
@@ -127,8 +133,7 @@ class MutualAction(DefineAction, LLMAction):
fb_label = fb_map.get(str(feedback).strip(), str(feedback))
feedback_event = Event(self.world.month_stamp, f"{target_avatar.name}{self.avatar.name} 的反馈:{fb_label}")
# 侧边栏仅推送一次,另一侧仅写入历史,避免重复
self.avatar.add_event(feedback_event)
target_avatar.add_event(feedback_event, to_sidebar=False)
self._add_event_pair(feedback_event, initiator=self.avatar, target=target_avatar)
# 4) 记录历史(文本记录)
self._apply_feedback(target_avatar, feedback)
@@ -214,11 +219,7 @@ class MoveAwayFromAvatar(DefineAction, ActualActionMixin):
DOABLES_REQUIREMENTS = "任何时候都可以执行"
PARAMS = {"avatar_name": "AvatarName"}
def _execute(self, avatar_name: str) -> None:
target = None
for v in self.world.avatar_manager.avatars.values():
if v.name == avatar_name:
target = v
break
target = self._find_avatar_by_name(avatar_name)
if target is None:
return
# 被攻击时逃跑的成功率:从 battle 模块获取(暂时固定值)
@@ -233,16 +234,13 @@ class MoveAwayFromAvatar(DefineAction, ActualActionMixin):
self.avatar.pos_y = ny
self.avatar.tile = self.world.map.get_tile(nx, ny)
else:
# 逃跑失败:进入战斗(立即动作)
self.avatar.clear_plans()
# 入队并提交
# 抢占:中断自身动作并清空队列后入队并提交
self._preempt_avatar(self.avatar)
self.avatar.load_decide_result_chain([("Battle", {"avatar_name": avatar_name})], self.avatar.thinking, "")
start_event = self.avatar.commit_next_plan()
if start_event is not None:
# 仅在本方推送到侧边栏;对方仅写历史
self.avatar.add_event(start_event)
if target is not None:
target.add_event(start_event, to_sidebar=False)
self._add_event_pair(start_event, initiator=self.avatar, target=target)
class MoveAwayFromRegion(DefineAction, ActualActionMixin):

View File

@@ -5,7 +5,7 @@
通用的动作说明为:
{general_action_infos}
注意只返回json格式结果。
注意只返回json格式结果且严格满足json格式
分Avatar进行返回格式为
{{
AvatarName: {{