update death
This commit is contained in:
@@ -9,6 +9,7 @@ from src.classes.battle import decide_battle, get_assassination_success_rate
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.normalize import normalize_avatar_name
|
||||
from src.classes.death import handle_death
|
||||
from src.classes.death_reason import DeathReason
|
||||
from src.classes.kill_and_grab import kill_and_grab
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -116,7 +117,7 @@ class Assassinate(InstantAction):
|
||||
story_event = Event(self.world.month_stamp, story, related_avatars=rel_ids, is_story=True)
|
||||
|
||||
# 死亡清理
|
||||
handle_death(self.world, target)
|
||||
handle_death(self.world, target, DeathReason.BATTLE)
|
||||
|
||||
return [result_event, story_event]
|
||||
|
||||
@@ -153,7 +154,7 @@ class Assassinate(InstantAction):
|
||||
story_event = Event(self.world.month_stamp, story, related_avatars=rel_ids, is_story=True)
|
||||
|
||||
if is_fatal:
|
||||
handle_death(self.world, loser)
|
||||
handle_death(self.world, loser, DeathReason.BATTLE)
|
||||
|
||||
return [result_event, story_event]
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from src.classes.battle import decide_battle, get_effective_strength_pair
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.normalize import normalize_avatar_name
|
||||
from src.classes.death import handle_death
|
||||
from src.classes.death_reason import DeathReason
|
||||
from src.classes.kill_and_grab import kill_and_grab
|
||||
|
||||
class Attack(InstantAction):
|
||||
@@ -109,6 +110,6 @@ class Attack(InstantAction):
|
||||
|
||||
# 如果死亡,执行死亡清理(在故事生成后,保证关系数据可用)
|
||||
if is_fatal:
|
||||
handle_death(self.world, loser)
|
||||
handle_death(self.world, loser, DeathReason.BATTLE)
|
||||
|
||||
return [result_event, story_event]
|
||||
|
||||
@@ -84,7 +84,8 @@ class Age:
|
||||
years_over_lifespan = self.age - expected
|
||||
|
||||
# 基础概率:每超过1年增加0.01的概率
|
||||
death_probability = min(years_over_lifespan * 0.01, 0.1)
|
||||
prob_add = 0.01
|
||||
death_probability = min(years_over_lifespan * prob_add, 0.1)
|
||||
|
||||
return death_probability
|
||||
|
||||
|
||||
@@ -114,6 +114,12 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
nickname: Optional[Nickname] = None
|
||||
# 自定义头像ID:如果设置,优先使用此ID显示头像
|
||||
custom_pic_id: Optional[int] = None
|
||||
|
||||
# 死亡状态
|
||||
is_dead: bool = False
|
||||
# 死亡信息:{ "time": MonthStamp, "reason": str, "location": (x, y) }
|
||||
death_info: Optional[dict] = None
|
||||
|
||||
# 当月/当步新设动作标记:在 commit_next_plan 设为 True,首次 tick_action 后清为 False
|
||||
_new_action_set_this_step: bool = False
|
||||
# 动作冷却:记录动作类名 -> 上次完成月戳
|
||||
@@ -122,6 +128,8 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
|
||||
def join_sect(self, sect: Sect, rank: "SectRank") -> None:
|
||||
"""加入宗门"""
|
||||
if self.is_dead:
|
||||
return
|
||||
if self.sect:
|
||||
self.leave_sect()
|
||||
self.sect = sect
|
||||
@@ -137,6 +145,38 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
self.sect = None
|
||||
self.sect_rank = None
|
||||
|
||||
def set_dead(self, reason: str, time: MonthStamp) -> None:
|
||||
"""
|
||||
设置角色死亡状态。
|
||||
|
||||
Args:
|
||||
reason: 死亡原因
|
||||
time: 死亡时间
|
||||
"""
|
||||
if self.is_dead:
|
||||
return
|
||||
|
||||
self.is_dead = True
|
||||
self.death_info = {
|
||||
"time": int(time),
|
||||
"reason": reason,
|
||||
"location": (self.pos_x, self.pos_y)
|
||||
}
|
||||
|
||||
# 清空所有计划和当前动作
|
||||
self.planned_actions.clear()
|
||||
self.current_action = None
|
||||
self._pending_events.clear()
|
||||
self.thinking = ""
|
||||
self.short_term_objective = ""
|
||||
|
||||
# 退出宗门(保留职位记录还是清除?通常死人不再担任职位)
|
||||
# 但为了历史记录,也许可以保留 sect 字段,但从宗门成员列表中移除
|
||||
if self.sect:
|
||||
self.sect.remove_member(self)
|
||||
# 不清除 self.sect 和 self.sect_rank,作为生平记录保留
|
||||
|
||||
|
||||
def __post_init__(self):
|
||||
"""
|
||||
在Avatar创建后自动初始化tile和HP
|
||||
@@ -319,6 +359,8 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
"long_term_objective": self.long_term_objective.content if self.long_term_objective else "",
|
||||
"nickname": self.nickname.value if self.nickname else None,
|
||||
"nickname_reason": self.nickname.reason if self.nickname else None,
|
||||
"is_dead": self.is_dead,
|
||||
"death_info": self.death_info,
|
||||
}
|
||||
|
||||
# 复杂对象结构化
|
||||
|
||||
@@ -26,6 +26,12 @@ class AvatarManager:
|
||||
same_region.append(other)
|
||||
return same_region
|
||||
|
||||
def get_living_avatars(self) -> List["Avatar"]:
|
||||
"""
|
||||
返回所有存活的角色列表。
|
||||
"""
|
||||
return [avatar for avatar in self.avatars.values() if not avatar.is_dead]
|
||||
|
||||
def get_observable_avatars(self, avatar: "Avatar") -> List["Avatar"]:
|
||||
"""
|
||||
返回处于 avatar 交互范围内的其他角色列表(不含自己)。
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from src.classes.death_reason import DeathReason
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.world import World
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
def handle_death(world: World, avatar: Avatar) -> None:
|
||||
def handle_death(world: World, avatar: Avatar, reason: Union[str, DeathReason] = DeathReason.UNKNOWN) -> None:
|
||||
"""
|
||||
处理角色死亡的统一入口。
|
||||
负责将角色从世界管理器中移除,并处理相关的清理工作(如关系解除已在 remove_avatar 中实现)。
|
||||
注意:本函数不负责生成死亡事件文本,调用者应在调用前生成相应的 Event。
|
||||
负责将角色标记为死亡,清理行动队列,但保留角色数据。
|
||||
|
||||
Args:
|
||||
world: 世界对象
|
||||
avatar: 死亡的角色
|
||||
reason: 死亡原因(DeathReason枚举或字符串)
|
||||
"""
|
||||
# 从管理器中移除角色(remove_avatar 内部会自动清理双向关系)
|
||||
world.avatar_manager.remove_avatar(avatar.id)
|
||||
# 如果传入的是枚举,转为字符串值
|
||||
reason_str = reason.value if isinstance(reason, DeathReason) else str(reason)
|
||||
|
||||
# 标记为死亡(软删除)
|
||||
avatar.set_dead(reason_str, world.month_stamp)
|
||||
|
||||
# 可以在这里触发其他逻辑,比如检查是否有继承人等
|
||||
|
||||
|
||||
|
||||
11
src/classes/death_reason.py
Normal file
11
src/classes/death_reason.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from enum import Enum
|
||||
|
||||
class DeathReason(Enum):
|
||||
OLD_AGE = "老死"
|
||||
BATTLE = "战死"
|
||||
SERIOUS_INJURY = "重伤"
|
||||
UNKNOWN = "未知"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
Reference in New Issue
Block a user