fix death bug

This commit is contained in:
bridge
2026-01-06 21:23:06 +08:00
parent 3f980d4593
commit b60481c99c
7 changed files with 157 additions and 93 deletions

View File

@@ -19,8 +19,8 @@ class Age:
def __init__(self, age: int, realm: Realm):
self.age = age
# 基础最大寿元不含effects加成,初始化为 max(境界基线, 当前年龄+1)
self.base_max_lifespan: int = max(self.get_base_expected_lifespan(realm), self.age + 1)
# 基础最大寿元不含effects加成
self.base_max_lifespan: int = self.get_base_expected_lifespan(realm)
# 实际最大寿元包含effects加成初始值与基础值相同
self.max_lifespan: int = self.base_max_lifespan
@@ -38,8 +38,7 @@ class Age:
def set_initial_max_lifespan(self, realm: Realm) -> None:
"""构造时已设置最大寿元,此处保持与构造策略一致。"""
base = self.get_base_expected_lifespan(realm)
self.base_max_lifespan = max(base, self.age + 1)
self.base_max_lifespan = self.get_base_expected_lifespan(realm)
self.max_lifespan = self.base_max_lifespan
def update_realm(self, new_realm: Realm) -> None:
@@ -48,11 +47,10 @@ class Age:
self.ensure_max_lifespan_at_least_realm_base(new_realm)
def ensure_max_lifespan_at_least_realm_base(self, realm: Realm) -> None:
"""确保基础最大寿元至少达到 max(该境界基线, 当前年龄+1)"""
"""确保基础最大寿元至少达到该境界基线"""
base = self.get_base_expected_lifespan(realm)
floor_value = max(base, self.age + 1)
if self.base_max_lifespan < floor_value:
self.base_max_lifespan = floor_value
if self.base_max_lifespan < base:
self.base_max_lifespan = base
self.max_lifespan = self.base_max_lifespan
def increase_max_lifespan(self, years: int) -> None:
@@ -85,7 +83,7 @@ class Age:
# 基础概率每超过1年增加0.01的概率
prob_add = 0.01
death_probability = min(years_over_lifespan * prob_add, 0.1)
death_probability = min(years_over_lifespan * prob_add, 0.01)
return death_probability

View File

@@ -14,6 +14,33 @@ class AvatarManager:
avatars: Dict[str, "Avatar"] = field(default_factory=dict)
# 存储已死亡的角色(归档)
dead_avatars: Dict[str, "Avatar"] = field(default_factory=dict)
# --- 变更缓冲区 (不参与序列化) ---
_newly_dead_buffer: List[str] = field(default_factory=list, init=False)
_newly_born_buffer: List[str] = field(default_factory=list, init=False)
def register_avatar(self, avatar: "Avatar", is_newly_born: bool = False) -> None:
"""
注册一个角色到管理器中。
Args:
avatar: 角色对象
is_newly_born: 是否为新出生的角色(若是,则加入变更缓冲供前端同步)
"""
self.avatars[str(avatar.id)] = avatar
if is_newly_born:
self._newly_born_buffer.append(str(avatar.id))
def pop_newly_dead(self) -> List[str]:
"""获取并清空本帧刚死亡的角色ID列表"""
res = list(self._newly_dead_buffer)
self._newly_dead_buffer.clear()
return res
def pop_newly_born(self) -> List[str]:
"""获取并清空本帧刚出生的角色ID列表"""
res = list(self._newly_born_buffer)
self._newly_born_buffer.clear()
return res
def get_avatar(self, avatar_id: str) -> "Avatar | None":
"""
@@ -33,6 +60,9 @@ class AvatarManager:
# 断开地图连接,确保不出现在地图网格上
if hasattr(avatar, "tile"):
avatar.tile = None
# 记录变更
self._newly_dead_buffer.append(aid)
def get_avatars_in_same_region(self, avatar: "Avatar") -> List["Avatar"]:
"""

View File

@@ -21,4 +21,7 @@ def handle_death(world: World, avatar: Avatar, reason: Union[str, DeathReason])
# 标记为死亡(软删除)
avatar.set_dead(reason_str, world.month_stamp)
# 从管理器中归档(硬移动),并记录变更
world.avatar_manager.handle_death(avatar.id)
# 可以在这里触发其他逻辑,比如检查是否有继承人等

View File

@@ -369,14 +369,9 @@ async def game_loop():
# 执行一步
events = await sim.step()
# 找出新诞生的角色 ID 和 刚死亡的角色 ID
newly_born_ids = set()
newly_dead_ids = set()
for e in events:
if "晋升为修士" in e.content and e.related_avatars:
newly_born_ids.update(e.related_avatars)
if ("身亡" in e.content or "老死" in e.content) and e.related_avatars:
newly_dead_ids.update(e.related_avatars)
# 获取状态变更 (Source of Truth: AvatarManager)
newly_born_ids = world.avatar_manager.pop_newly_born()
newly_dead_ids = world.avatar_manager.pop_newly_dead()
avatar_updates = []
@@ -411,8 +406,6 @@ async def game_loop():
"is_dead": True,
"action": "已故"
})
# 将死者归档到墓地,从活跃列表移除
world.avatar_manager.handle_death(aid)
# 3. 常规位置更新(暂时只发前 50 个旧角色,减少数据量)
limit = 50
@@ -1063,7 +1056,7 @@ def create_avatar(req: CreateAvatarRequest):
avatar.alignment = Alignment.from_str(req.alignment)
# 注册到管理器
world.avatar_manager.avatars[avatar.id] = avatar
world.avatar_manager.register_avatar(avatar, is_newly_born=True)
return {
"status": "ok",

View File

@@ -173,7 +173,7 @@ class Simulator:
death_reason = DeathReason(DeathType.OLD_AGE)
if is_dead and death_reason:
event = Event(self.world.month_stamp, str(death_reason), related_avatars=[avatar.id])
event = Event(self.world.month_stamp, f"{avatar.name}{death_reason}", related_avatars=[avatar.id])
events.append(event)
handle_death(self.world, avatar, death_reason)
@@ -192,7 +192,7 @@ class Simulator:
name = get_random_name(gender)
# create_random_mortal 内部会获取 existing_avatars需要确保它处理活人
new_avatar = create_random_mortal(self.world, self.world.month_stamp, name, Age(age, Realm.Qi_Refinement))
self.world.avatar_manager.avatars[new_avatar.id] = new_avatar
self.world.avatar_manager.register_avatar(new_avatar, is_newly_born=True)
event = Event(self.world.month_stamp, f"{new_avatar.name}晋升为修士了。", related_avatars=[new_avatar.id])
events.append(event)
return events