fix: incorrect relationship for new avatar
This commit is contained in:
@@ -236,7 +236,9 @@ class PopulationPlanner:
|
||||
planned_surname[a] = surname
|
||||
planned_surname[b] = surname
|
||||
planned_gender[a] = Gender.MALE
|
||||
planned_relations[(a, b)] = Relation.CHILD
|
||||
# 设定 a 为父,b 为子
|
||||
# (a, b) = PARENT -> a.relations[b] = PARENT (a 视 b 为子)
|
||||
planned_relations[(a, b)] = Relation.PARENT
|
||||
else:
|
||||
mother = a if random.random() < 0.5 else b
|
||||
child = b if mother == a else a
|
||||
@@ -248,7 +250,8 @@ class PopulationPlanner:
|
||||
if s != mom_surname:
|
||||
planned_surname[child] = s
|
||||
break
|
||||
planned_relations[(mother, child)] = Relation.CHILD
|
||||
# (mother, child) = PARENT -> mother.relations[child] = PARENT
|
||||
planned_relations[(mother, child)] = Relation.PARENT
|
||||
|
||||
leftover = unused_indices[:]
|
||||
|
||||
@@ -448,10 +451,11 @@ class AvatarFactory:
|
||||
if attach_relations:
|
||||
if plan.parent_avatar is not None:
|
||||
# plan.parent_avatar 是长辈
|
||||
# 设置关系:长辈.set_relation(自己, CHILD)
|
||||
# 底层逻辑:长辈.relations[自己] = CHILD (长辈认为自己是孩子)
|
||||
# 自己.relations[长辈] = PARENT (自己认为长辈是父母)
|
||||
plan.parent_avatar.set_relation(avatar, Relation.CHILD)
|
||||
# 设置关系:长辈.set_relation(自己, PARENT)
|
||||
# 底层逻辑:长辈.relations[自己] = PARENT (长辈认为自己是父母 -> 错误,是长辈认为自己是子女?)
|
||||
# 修正:Relation.PARENT 映射显示为“儿子/女儿”,即 relations[X]=PARENT 意味着 X 是儿子/女儿
|
||||
# 所以 plan.parent_avatar.relations[avatar] = PARENT 是正确的,表示 parent 视 avatar 为子女
|
||||
plan.parent_avatar.set_relation(avatar, Relation.PARENT)
|
||||
if plan.master_avatar is not None:
|
||||
# plan.master_avatar 是师傅
|
||||
# 设置关系:师傅.set_relation(自己, APPRENTICE)
|
||||
|
||||
126
tests/test_new_avatar_relation.py
Normal file
126
tests/test_new_avatar_relation.py
Normal file
@@ -0,0 +1,126 @@
|
||||
import pytest
|
||||
from src.classes.world import World
|
||||
from src.classes.calendar import MonthStamp
|
||||
from src.classes.age import Age
|
||||
from src.classes.avatar import Avatar, Gender
|
||||
from src.classes.relation import Relation, get_relation_label
|
||||
from src.classes.cultivation import CultivationProgress, Realm
|
||||
from src.utils.id_generator import get_avatar_id
|
||||
from src.sim.new_avatar import create_random_mortal, MortalPlanner, AvatarFactory, PopulationPlanner
|
||||
|
||||
@pytest.fixture
|
||||
def mock_world(base_world):
|
||||
return base_world
|
||||
|
||||
def test_single_mortal_relation(mock_world):
|
||||
"""测试单个新角色生成时的亲子关系方向是否正确"""
|
||||
# 1. 创建一个假设的父母角色
|
||||
parent_avatar = Avatar(
|
||||
world=mock_world,
|
||||
name="Parent",
|
||||
id=get_avatar_id(),
|
||||
birth_month_stamp=MonthStamp(0),
|
||||
age=Age(100, Realm.Core_Formation),
|
||||
gender=Gender.FEMALE,
|
||||
cultivation_progress=CultivationProgress(60), # 金丹期
|
||||
pos_x=0,
|
||||
pos_y=0
|
||||
)
|
||||
# 加入世界管理器
|
||||
mock_world.avatar_manager.register_avatar(parent_avatar)
|
||||
|
||||
# 2. 创建一个新角色,作为子女
|
||||
# 我们通过强制指定 parent_avatar 来测试关系设置逻辑
|
||||
# 由于 create_random_mortal 内部逻辑有随机性,这里直接使用底层 factory 并构造 plan
|
||||
|
||||
child_age = Age(20, Realm.Qi_Refinement)
|
||||
plan = MortalPlanner.plan(mock_world, "Child", child_age, level=10, allow_relations=False)
|
||||
|
||||
# 手动指定父母,模拟 random 选中的情况
|
||||
plan.parent_avatar = parent_avatar
|
||||
|
||||
child_avatar = AvatarFactory.build_from_plan(
|
||||
mock_world,
|
||||
mock_world.month_stamp,
|
||||
name="Child",
|
||||
age=child_age,
|
||||
plan=plan,
|
||||
attach_relations=True
|
||||
)
|
||||
|
||||
# 3. 验证关系
|
||||
# 父母看子女:应该是 PARENT (映射为 儿子/女儿)
|
||||
rel_from_parent = parent_avatar.get_relation(child_avatar)
|
||||
assert rel_from_parent == Relation.PARENT, f"父母看子女应该是 PARENT, 但得到了 {rel_from_parent}"
|
||||
|
||||
label_from_parent = get_relation_label(rel_from_parent, parent_avatar, child_avatar)
|
||||
# 因为 child 性别随机,可能是 儿子 或 女儿
|
||||
assert label_from_parent in ["儿子", "女儿"], f"父母看子女的称谓错误: {label_from_parent}"
|
||||
|
||||
# 子女看父母:应该是 CHILD (映射为 父亲/母亲)
|
||||
rel_from_child = child_avatar.get_relation(parent_avatar)
|
||||
assert rel_from_child == Relation.CHILD, f"子女看父母应该是 CHILD, 但得到了 {rel_from_child}"
|
||||
|
||||
label_from_child = get_relation_label(rel_from_child, child_avatar, parent_avatar)
|
||||
assert label_from_child == "母亲", f"子女看母亲的称谓错误: {label_from_child}" # parent 是 FEMALE
|
||||
|
||||
|
||||
def test_population_planner_relations(mock_world):
|
||||
"""测试批量生成时的亲子关系方向是否正确"""
|
||||
# 强制生成一组角色,通过大量生成来触发家庭关系
|
||||
# 为了提高概率,我们直接调用 PopulationPlanner 内部逻辑或者检查生成后的结果
|
||||
|
||||
# 尝试生成 20 个角色,期望出现家庭关系
|
||||
count = 20
|
||||
avatars_dict = PopulationPlanner.plan_group(count, existed_sects=None)
|
||||
|
||||
# 检查计划中的关系
|
||||
relations = avatars_dict.relations
|
||||
|
||||
if not relations:
|
||||
pytest.skip("本次随机未生成任何关系,跳过测试")
|
||||
return
|
||||
|
||||
found_parent_relation = False
|
||||
|
||||
for (a_idx, b_idx), rel in relations.items():
|
||||
if rel == Relation.PARENT:
|
||||
found_parent_relation = True
|
||||
# 在 plan_group 中,(a, b) = PARENT 意味着 a 是父母,b 是子女
|
||||
# 这里的语义是:a 的 relations 中,对 b 的记录是 PARENT
|
||||
pass
|
||||
|
||||
# 如果找到了 PARENT 关系,说明代码中使用了 Relation.PARENT 而不是之前的 Relation.CHILD
|
||||
# 之前的代码是用 Relation.CHILD,修正后应该是 Relation.PARENT
|
||||
|
||||
# 进一步:实际构建角色并验证
|
||||
avatars_map = AvatarFactory.build_group(mock_world, mock_world.month_stamp, avatars_dict)
|
||||
avatars = list(avatars_map.values())
|
||||
|
||||
# 由于 build_group 返回的是 dict[id, Avatar],且顺序可能打乱,我们需要重新映射 index
|
||||
# 但我们其实只需要遍历所有 Avatar 检查关系即可
|
||||
|
||||
for av in avatars:
|
||||
for target, rel in av.relations.items():
|
||||
if rel == Relation.PARENT:
|
||||
# av 认为是父母 -> target 是子女
|
||||
# 验证年龄:父母应该比子女大
|
||||
assert av.age.age > target.age.age, f"父母({av.name}, {av.age.age}) 应该比子女({target.name}, {target.age.age}) 大"
|
||||
|
||||
# 验证称谓
|
||||
label = get_relation_label(rel, av, target)
|
||||
assert label in ["儿子", "女儿"]
|
||||
|
||||
elif rel == Relation.CHILD:
|
||||
# av 认为是子女 -> target 是父母
|
||||
# 验证年龄:子女应该比父母小
|
||||
assert av.age.age < target.age.age, f"子女({av.name}, {av.age.age}) 应该比父母({target.name}, {target.age.age}) 小"
|
||||
|
||||
# 验证称谓
|
||||
label = get_relation_label(rel, av, target)
|
||||
assert label in ["父亲", "母亲"]
|
||||
|
||||
if not found_parent_relation:
|
||||
# 如果随机没随到家庭,我们可以认为只要没报错且逻辑通顺就行,
|
||||
# 或者可以 mock random 来强制覆盖路径,但在集成测试中只要多跑几次通常能覆盖
|
||||
pass
|
||||
Reference in New Issue
Block a user