update map
This commit is contained in:
@@ -26,7 +26,7 @@ class Talk(InstantAction):
|
||||
# Talk 本身不做长期效果,主要在 step 中驱动 Conversation
|
||||
return
|
||||
|
||||
def can_start(self) -> bool:
|
||||
def can_start(self, **kwargs) -> bool:
|
||||
# 感知范围内是否存在其他NPC(用于展示在动作空间)
|
||||
return len(self._get_observed_others()) > 0
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ from src.utils.config import CONFIG
|
||||
from src.classes.relation import Relation, get_reciprocal
|
||||
from src.run.log import get_logger
|
||||
from src.classes.alignment import Alignment
|
||||
from src.classes.sect import Sect
|
||||
|
||||
persona_num = CONFIG.avatar.persona_num
|
||||
|
||||
@@ -77,7 +78,9 @@ class Avatar:
|
||||
hp: HP = field(default_factory=lambda: HP(0, 0)) # 将在__post_init__中初始化
|
||||
mp: MP = field(default_factory=lambda: MP(0, 0)) # 将在__post_init__中初始化
|
||||
relations: dict["Avatar", Relation] = field(default_factory=dict)
|
||||
alignment: Alignment = field(default_factory=lambda: random.choice(list(Alignment)))
|
||||
alignment: Alignment | None = None
|
||||
# 所属宗门(可为空,表示散修/无门无派)
|
||||
sect: Sect | None = None
|
||||
# 当月/当步新设动作标记:在 commit_next_plan 设为 True,首次 tick_action 后清为 False
|
||||
_new_action_set_this_step: bool = False
|
||||
|
||||
@@ -103,6 +106,14 @@ class Avatar:
|
||||
if self.technique is None:
|
||||
self.technique = get_random_technique_for_avatar(self)
|
||||
|
||||
# 若未设定阵营,则依据宗门/无门无派规则设置,避免后续为 None
|
||||
if self.alignment is None:
|
||||
if self.sect is not None:
|
||||
self.alignment = self.sect.alignment
|
||||
else:
|
||||
from src.classes.alignment import Alignment as _Alignment
|
||||
self.alignment = random.choice(list(_Alignment))
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
|
||||
@@ -113,7 +124,8 @@ class Avatar:
|
||||
"""
|
||||
personas_str = ", ".join([persona.name for persona in self.personas])
|
||||
technique_str = self.technique.name if self.technique is not None else "无"
|
||||
return f"Avatar(id={self.id}, 性别={self.gender}, 年龄={self.age}, name={self.name}, 阵营={self.alignment.get_info()}, 区域={self.tile.region.name}, 灵根={str(self.root)}, 功法={technique_str}, 境界={self.cultivation_progress}, HP={self.hp}, MP={self.mp}, 个性={personas_str})"
|
||||
sect_str = self.get_sect_str()
|
||||
return f"Avatar(id={self.id}, 性别={self.gender}, 年龄={self.age}, name={self.name}, 宗门={sect_str}, 阵营={self.alignment.get_info()}, 区域={self.tile.region.name}, 灵根={str(self.root)}, 功法={technique_str}, 境界={self.cultivation_progress}, HP={self.hp}, MP={self.mp}, 个性={personas_str})"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.get_info()
|
||||
@@ -397,6 +409,13 @@ class Avatar:
|
||||
# 关系摘要
|
||||
relations_summary = self._get_relations_summary_str()
|
||||
|
||||
# 宗门信息
|
||||
sect_name = self.get_sect_str()
|
||||
if self.sect is not None:
|
||||
sect_info = f"宗门信息:{sect_name},风格:{self.sect.member_act_style}"
|
||||
else:
|
||||
sect_info = f"宗门信息:{sect_name}"
|
||||
|
||||
# 历史事件摘要
|
||||
if self.history_events:
|
||||
history_lines = ";".join([str(e) for e in self.history_events[-8:]])
|
||||
@@ -404,7 +423,66 @@ class Avatar:
|
||||
else:
|
||||
history_info = "历史事件:无"
|
||||
|
||||
return f"{info}\n{personas_info}\n{magic_stone_info}\n{items_info}\n{history_info}\n关系:{relations_summary}\n{co_region_info}\n该角色的目前合法动作为:{action_space}"
|
||||
return f"{info}\n{sect_info}\n{personas_info}\n{magic_stone_info}\n{items_info}\n{history_info}\n关系:{relations_summary}\n{co_region_info}\n该角色的目前合法动作为:{action_space}"
|
||||
|
||||
def get_hover_info(self) -> list[str]:
|
||||
"""
|
||||
返回用于前端悬浮提示的多行信息。
|
||||
"""
|
||||
lines: list[str] = [
|
||||
f"{self.name}",
|
||||
f"性别: {self.gender}",
|
||||
f"年龄: {self.age}",
|
||||
f"阵营: {self.alignment}",
|
||||
f"境界: {str(self.cultivation_progress)}",
|
||||
f"HP: {self.hp}",
|
||||
f"MP: {self.mp}",
|
||||
]
|
||||
lines.append(f"宗门: {self.get_sect_str()}")
|
||||
from src.classes.root import format_root_cn
|
||||
lines.append(f"灵根: {format_root_cn(self.root)}")
|
||||
if self.technique is not None:
|
||||
lines.append(f"功法: {self.technique.name}({self.technique.attribute}·{self.technique.grade.value})")
|
||||
else:
|
||||
lines.append("功法: 无")
|
||||
if self.personas:
|
||||
lines.append(f"个性: {', '.join([persona.name for persona in self.personas])}")
|
||||
lines.append(f"位置: ({self.pos_x}, {self.pos_y})")
|
||||
lines.append(f"灵石: {str(self.magic_stone)}")
|
||||
if self.items:
|
||||
lines.append("物品:")
|
||||
for item, quantity in self.items.items():
|
||||
lines.append(f" {item.name} x{quantity}")
|
||||
else:
|
||||
lines.append("")
|
||||
lines.append("物品: 无")
|
||||
if self.thinking:
|
||||
lines.append("")
|
||||
lines.append("思考:")
|
||||
from src.utils.text_wrap import wrap_text
|
||||
lines.extend(wrap_text(self.thinking, 28))
|
||||
if getattr(self, "objective", None):
|
||||
lines.append("")
|
||||
lines.append("目标:")
|
||||
from src.utils.text_wrap import wrap_text
|
||||
lines.extend(wrap_text(self.objective, 28))
|
||||
|
||||
# 关系信息
|
||||
lines.append("")
|
||||
relations_list = [f"{other.name}({str(relation)})" for other, relation in getattr(self, "relations", {}).items()]
|
||||
if relations_list:
|
||||
lines.append("关系:")
|
||||
for s in relations_list[:6]:
|
||||
lines.append(f" {s}")
|
||||
else:
|
||||
lines.append("关系: 无")
|
||||
return lines
|
||||
|
||||
def get_sect_str(self) -> str:
|
||||
"""
|
||||
获取宗门显示名:有宗门则返回宗门名,否则返回"散修"。
|
||||
"""
|
||||
return self.sect.name if self.sect is not None else "散修"
|
||||
|
||||
def set_relation(self, other: "Avatar", relation: Relation) -> None:
|
||||
"""
|
||||
|
||||
@@ -158,6 +158,16 @@ class Region(ABC):
|
||||
"""返回区域类型的字符串表示"""
|
||||
pass
|
||||
|
||||
def get_hover_info(self) -> list[str]:
|
||||
"""
|
||||
返回用于前端悬浮提示的多行信息(基础信息)。
|
||||
子类可扩展更多领域信息。
|
||||
"""
|
||||
return [
|
||||
f"区域: {self.name}",
|
||||
f"描述: {self.desc}",
|
||||
]
|
||||
|
||||
|
||||
class Shape(Enum):
|
||||
"""
|
||||
@@ -235,6 +245,17 @@ class NormalRegion(Region):
|
||||
species_info = self.get_species_info()
|
||||
return f"普通区域:{self.name} - {self.desc} | 物种分布:{species_info}"
|
||||
|
||||
def get_hover_info(self) -> list[str]:
|
||||
lines = super().get_hover_info()
|
||||
species_info = self.get_species_info()
|
||||
if species_info and species_info != "暂无特色物种":
|
||||
lines.append("物种分布:")
|
||||
for species in species_info.split("; "):
|
||||
lines.append(f" {species}")
|
||||
else:
|
||||
lines.append("物种分布: 暂无特色物种")
|
||||
return lines
|
||||
|
||||
@property
|
||||
def is_huntable(self) -> bool:
|
||||
# 如果该区域有动物,则可以狩猎
|
||||
@@ -270,6 +291,12 @@ class CultivateRegion(Region):
|
||||
def __str__(self) -> str:
|
||||
return f"修炼区域:{self.name}({self.essence_type}行灵气:{self.essence_density})- {self.desc}"
|
||||
|
||||
def get_hover_info(self) -> list[str]:
|
||||
lines = super().get_hover_info()
|
||||
stars = "★" * self.essence_density + "☆" * (10 - self.essence_density)
|
||||
lines.append(f"主要灵气: {self.essence_type} {stars}")
|
||||
return lines
|
||||
|
||||
|
||||
@dataclass
|
||||
class CityRegion(Region):
|
||||
@@ -283,6 +310,10 @@ class CityRegion(Region):
|
||||
def __str__(self) -> str:
|
||||
return f"城市区域:{self.name} - {self.desc}"
|
||||
|
||||
def get_hover_info(self) -> list[str]:
|
||||
# 城市区域暂时仅展示基础信息
|
||||
return super().get_hover_info()
|
||||
|
||||
|
||||
T = TypeVar('T', NormalRegion, CultivateRegion, CityRegion)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ class SectHeadQuarter:
|
||||
宗门总部
|
||||
"""
|
||||
name: str
|
||||
desc: str
|
||||
image: Path
|
||||
|
||||
@dataclass
|
||||
@@ -26,7 +27,8 @@ class Sect:
|
||||
member_act_style: str
|
||||
alignment: Alignment
|
||||
sect_surnames: list[str]
|
||||
sect_given_names: list[str]
|
||||
male_sect_given_names: list[str]
|
||||
female_sect_given_names: list[str]
|
||||
headquarter: SectHeadQuarter
|
||||
# 功法:在technique.csv中配置
|
||||
# TODO:法宝
|
||||
@@ -47,16 +49,23 @@ def _load_sects() -> tuple[dict[int, Sect], dict[str, Sect]]:
|
||||
assets_base = Path("assets/sects")
|
||||
for _, row in df.iterrows():
|
||||
image_path = assets_base / f"{row['name']}.png"
|
||||
male_given_names = _split_names(row["male_sect_given_names"])
|
||||
female_given_names = _split_names(row["female_sect_given_names"])
|
||||
|
||||
sect = Sect(
|
||||
id=int(row["id"]),
|
||||
name=str(row["name"]),
|
||||
desc=str(row["desc"]),
|
||||
member_act_style=str(row["member_act_style"]),
|
||||
alignment=Alignment.from_str(row.get("alignment", "中")),
|
||||
sect_surnames=_split_names(row.get("sect_surnames", "")),
|
||||
sect_given_names=_split_names(row.get("sect_given_names", "")),
|
||||
headquarter=SectHeadQuarter(name=str(row["name"]), image=image_path),
|
||||
alignment=Alignment.from_str(row["alignment"]),
|
||||
sect_surnames=_split_names(row["sect_surnames"]),
|
||||
male_sect_given_names=male_given_names,
|
||||
female_sect_given_names=female_given_names,
|
||||
headquarter=SectHeadQuarter(
|
||||
name=(str(row["headquarter_name"]) if str(row["headquarter_name"]).strip() else str(row["name"])),
|
||||
desc=str(row["headquarter_desc"]),
|
||||
image=image_path,
|
||||
),
|
||||
)
|
||||
sects_by_id[sect.id] = sect
|
||||
sects_by_name[sect.name] = sect
|
||||
|
||||
Reference in New Issue
Block a user