diff --git a/src/classes/age.py b/src/classes/age.py index e3fe66e..7a3f0c3 100644 --- a/src/classes/age.py +++ b/src/classes/age.py @@ -10,10 +10,10 @@ class Age: # 各境界的基础期望寿命(年) REALM_LIFESPAN = { - Realm.Qi_Refinement: 80, # 练气期:100年 - Realm.Foundation_Establishment: 120, # 筑基期:200年 - Realm.Core_Formation: 200, # 金丹期:500年 - Realm.Nascent_Soul: 500, # 元婴期:1000年 + Realm.Qi_Refinement: 100, # 练气期:100年 + Realm.Foundation_Establishment: 150, # 筑基期:150年 + Realm.Core_Formation: 200, # 金丹期:200年 + Realm.Nascent_Soul: 500, # 元婴期:500年 } @@ -71,21 +71,28 @@ class Age: """ 计算当月老死的概率 - 返回: - 老死概率,范围0.0-0.1 + 逻辑变更: + 1. age >= max_lifespan: 必死 (概率 1.0) + 2. age >= max_lifespan - 20: 进入衰老期,有概率死亡 + 3. 其他: 安全 """ expected = self.max_lifespan if realm is None else self.get_expected_lifespan(realm) - if self.age < expected: - return 0.0 - # 超过期望寿命的年数 - years_over_lifespan = self.age - expected + # 1. 超过大限,必死 + if self.age >= expected: + return 1.0 + + # 2. 距离大限20年内 (Twilight Years) + start_decay_age = max(0, expected - 20) - # 基础概率:每超过1年增加0.01的概率 - prob_add = 0.01 - death_probability = min(years_over_lifespan * prob_add, 0.01) - - return death_probability + if self.age >= start_decay_age: + # 概率设计:随年龄线性递增 + decay_years = self.age - start_decay_age + # 每接近大限一年,月死亡率增加 0.5% + return decay_years * 0.005 + + # 3. 安全期 + return 0.0 def death_by_old_age(self, realm: Realm) -> bool: """ diff --git a/static/locales/en-US/game_configs/world_info.csv b/static/locales/en-US/game_configs/world_info.csv index 8b80a4a..20744b0 100644 --- a/static/locales/en-US/game_configs/world_info.csv +++ b/static/locales/en-US/game_configs/world_info.csv @@ -2,7 +2,7 @@ title,desc Title,Description Introduction,This is a cultivation world where many cultivators compete to ascend. Realm,"Cultivation realms from weak to strong: Qi Refinement, Foundation Establishment, Core Formation, Nascent Soul. Each realm is divided into Early, Middle, and Late stages. The gap between realms is immense." -Lifespan,Every character has a lifespan. Exceeding it leads to death by old age. Advancing realms and certain treasures or elixirs can increase lifespan. +Lifespan,Every character has a maximum lifespan. In the 20 years before this limit, the body weakens, risking death by old age. Upon reaching or exceeding the limit, death is certain. Advancing realms and certain treasures or elixirs can increase maximum lifespan. Death,You will also die if HP drops below 0. Region,Different regions have different effects. Doing the right thing in the right region yields double the results with half the effort. Cultivate,Cultivation increases experience until reaching a bottleneck. Breakthrough is probabilistic; success leads to the next realm. diff --git a/static/locales/zh-CN/game_configs/world_info.csv b/static/locales/zh-CN/game_configs/world_info.csv index e79d9dd..264a09d 100644 --- a/static/locales/zh-CN/game_configs/world_info.csv +++ b/static/locales/zh-CN/game_configs/world_info.csv @@ -2,7 +2,7 @@ title,desc 标题,描述 简介,这是一个诸多修士竞相修行的修仙世界。 境界,修仙的境界从弱到强:练气、筑基、金丹、元婴。每个境界分前期、中期、后期。境界间差距很大。 -寿元,每个角色均有寿元,超过寿元后容易老死。提升境界和某些宝物、丹药能提高寿元。 +寿元,每个角色均有寿元上限。在大限将至的前20年身体会逐渐衰弱,有几率老死;一旦达到或超过寿元上限,则必死无疑。提升境界和某些宝物、丹药能提高寿元上限。 死亡,HP降至0以下也会死亡。 区域,不同区域有不同效果,在适当的区域做适当的事情事半功倍。 修炼,修炼可以增加经验,直到到达突破前的瓶颈。突破是概率事件,突破后会进入下一个境界。 diff --git a/tests/test_age_death_mechanic.py b/tests/test_age_death_mechanic.py new file mode 100644 index 0000000..c520013 --- /dev/null +++ b/tests/test_age_death_mechanic.py @@ -0,0 +1,84 @@ +import pytest +from src.classes.age import Age +from src.classes.cultivation import Realm + +class TestAgeDeathMechanic: + """测试新的寿命与老死机制""" + + def test_safe_zone(self): + """测试安全期:年龄 < 寿命上限 - 20""" + # 练气期寿命 100 + age = Age(50, Realm.Qi_Refinement) + assert age.max_lifespan == 100 + + # 50岁肯定安全 + assert age.get_death_probability() == 0.0 + + # 79岁也安全 (100 - 20 = 80) + age.age = 79 + assert age.get_death_probability() == 0.0 + + def test_twilight_zone(self): + """测试衰退期:寿命上限 - 20 <= 年龄 < 寿命上限""" + # 练气期寿命 100,衰退期开始于 80 + age = Age(80, Realm.Qi_Refinement) + + # 刚进入衰退期 + prob_80 = age.get_death_probability() + assert prob_80 == 0.0 # (80 - 80) * 0.005 = 0 + + # 81岁 + age.age = 81 + prob_81 = age.get_death_probability() + assert prob_81 > 0.0 + assert prob_81 == 0.005 # (81 - 80) * 0.005 + + # 90岁 + age.age = 90 + prob_90 = age.get_death_probability() + assert prob_90 == 0.05 # (90 - 80) * 0.005 + + # 99岁 + age.age = 99 + prob_99 = age.get_death_probability() + assert prob_99 > prob_90 + assert prob_99 < 1.0 + + def test_doom_zone(self): + """测试大限:年龄 >= 寿命上限""" + age = Age(100, Realm.Qi_Refinement) + + # 刚好到达大限 + assert age.get_death_probability() == 1.0 + + # 超过大限 + age.age = 101 + assert age.get_death_probability() == 1.0 + + def test_realm_breakthrough_extends_life(self): + """测试突破境界延长寿命,脱离危险区""" + # 练气期 90岁 (寿命100),处于危险区 + age = Age(90, Realm.Qi_Refinement) + assert age.get_death_probability() > 0.0 + + # 突破到筑基期 (寿命150) + age.update_realm(Realm.Foundation_Establishment) + assert age.max_lifespan == 150 + + # 90岁对于150岁上限来说,远未到危险区 (150-20=130) + assert age.get_death_probability() == 0.0 + + def test_lifespan_reduction_items(self): + """测试寿命上限减少导致提前进入危险区""" + age = Age(50, Realm.Qi_Refinement) + assert age.max_lifespan == 100 + + # 遭受重创,折寿40年 -> 上限变60 + age.decrease_max_lifespan(40) + assert age.max_lifespan == 60 + + # 50岁对于60岁上限来说,已进入危险区 (60-20=40) + assert age.get_death_probability() > 0.0 + # (50 - 40) * 0.005 = 0.05 + assert age.get_death_probability() == 0.05 + diff --git a/tests/test_new_avatar.py b/tests/test_new_avatar.py index ed8d2b5..540d830 100644 --- a/tests/test_new_avatar.py +++ b/tests/test_new_avatar.py @@ -28,16 +28,28 @@ class TestAgeLifespanConstraint: ) def test_batch_creation_no_immediate_death(self, base_world): - """批量创建的角色不应该一出生就处于老死状态.""" + """批量创建的角色不应该一出生就处于必死状态. + + 注:新机制下,大限前20年会有死亡概率,所以不能断言概率为0, + 只能断言概率不为1.0(即没死透)。 + """ avatars = make_avatars(base_world, count=100) for avatar in avatars.values(): - # 不应该有老死概率 death_prob = avatar.age.get_death_probability() - assert death_prob == 0.0, ( - f"角色 {avatar.name} 年龄 {avatar.age.age}/" - f"{avatar.age.max_lifespan} 有老死概率 {death_prob}" + + # 1. 刚生成的活人角色不应该必死 + assert death_prob < 1.0, ( + f"角色 {avatar.name} 刚生成就必死 (prob={death_prob})" ) + + # 2. 如果在安全期,概率应为0 + safe_limit = avatar.age.max_lifespan - 20 + if avatar.age.age < safe_limit: + assert death_prob == 0.0, ( + f"角色 {avatar.name} 处于安全期 ({avatar.age.age}/{safe_limit}) " + f"却有老死概率 {death_prob}" + ) def test_multiple_batch_creations_consistent(self, base_world): """多次批量创建应该都满足年龄约束.""" @@ -54,7 +66,7 @@ class TestRealmLifespanMapping: """测试各境界的寿命上限映射.""" def test_qi_refinement_lifespan(self, base_world): - """练气期角色年龄应不超过80岁.""" + """练气期角色年龄应不超过100岁.""" from src.classes.cultivation import Realm avatars = make_avatars(base_world, count=100) @@ -63,13 +75,16 @@ class TestRealmLifespanMapping: if av.cultivation_progress.realm == Realm.Qi_Refinement ] + # 获取当前配置的寿命 + limit = Age.REALM_LIFESPAN[Realm.Qi_Refinement] + for avatar in qi_refinement_avatars: - assert avatar.age.age < 80, ( - f"练气期角色 {avatar.name} 年龄 {avatar.age.age} 超过 80" + assert avatar.age.age < limit, ( + f"练气期角色 {avatar.name} 年龄 {avatar.age.age} 超过 {limit}" ) def test_foundation_establishment_lifespan(self, base_world): - """筑基期角色年龄应不超过120岁.""" + """筑基期角色年龄应不超过150岁.""" from src.classes.cultivation import Realm avatars = make_avatars(base_world, count=100) @@ -78,7 +93,10 @@ class TestRealmLifespanMapping: if av.cultivation_progress.realm == Realm.Foundation_Establishment ] + # 获取当前配置的寿命 + limit = Age.REALM_LIFESPAN[Realm.Foundation_Establishment] + for avatar in fe_avatars: - assert avatar.age.age < 120, ( - f"筑基期角色 {avatar.name} 年龄 {avatar.age.age} 超过 120" + assert avatar.age.age < limit, ( + f"筑基期角色 {avatar.name} 年龄 {avatar.age.age} 超过 {limit}" )