diff --git a/src/classes/alignment.py b/src/classes/alignment.py index 0c80549..382e04c 100644 --- a/src/classes/alignment.py +++ b/src/classes/alignment.py @@ -14,7 +14,12 @@ class Alignment(Enum): return alignment_strs.get(self, self.value) def get_info(self) -> str: - return alignment_strs[self] + ": " + alignment_infos[self] + # 简版:仅返回短中文 + return alignment_strs[self] + + def get_detailed_info(self) -> str: + # 详细版:短中文 + 详细描述 + 关键词提示 + return f"{alignment_strs[self]}:{alignment_infos[self]}" def __hash__(self) -> int: return hash(self.value) @@ -58,4 +63,3 @@ alignment_infos = { Alignment.NEUTRAL: "中立阵营的理念是:顺势而为,趋利避害,重视自度与平衡,不轻易站队。", Alignment.EVIL: "邪恶阵营的理念是:弱肉强食,以自身利益为先,蔑视规则,推崇权力与恐惧。", } - diff --git a/src/classes/avatar.py b/src/classes/avatar.py index d4a2c30..560ec7d 100644 --- a/src/classes/avatar.py +++ b/src/classes/avatar.py @@ -120,16 +120,53 @@ class Avatar: def __hash__(self) -> int: return hash(self.id) - def get_info(self) -> str: + def get_info(self, detailed: bool = False) -> str: """ - 获取avatar的详细信息 - 尽量多打一些,因为会用来给LLM进行决策 + 获取avatar的信息,分详细和不详细两种。 """ - personas_str = ", ".join([persona.name for persona in self.personas]) - technique_str = self.technique.get_info() - sect_str = self.get_sect_str() - region_name = self.tile.region.name if self.tile.region is not None else "无" - return f"Avatar(id={self.id}, 性别={self.gender}, 年龄={self.age}, name={self.name}, 宗门={sect_str}, 阵营={self.alignment.get_info()}, 区域={region_name}, 灵根={str(self.root)}, 功法={technique_str}, 境界={self.cultivation_progress}, HP={self.hp}, MP={self.mp}, 个性={personas_str})" + region_info = "无" + region = self.tile.region if self.tile is not None else None + relations_info = self._get_relations_summary_str() + magic_stone_info = str(self.magic_stone) + + info = "Avatar:\n" + info += f"id={self.id}\n" + info += f"name={self.name}\n" + info += f"gender={self.gender}\n" + info += f"age={self.age}\n" + info += f"hp={self.hp}\n" + info += f"mp={self.mp}\n" + info += f"magic_stone={magic_stone_info}\n" + info += f"relations={relations_info}\n" + + # 接下来开始有区分了 + if detailed: + sect_info = self.sect.get_detailed_info() if self.sect is not None else "散修" + alignment_info = self.alignment.get_detailed_info() if self.alignment is not None else "未知" + region_info = region.get_detailed_info() if region is not None else "无" + root_info = self.root.get_detailed_info() + technique_info = self.technique.get_detailed_info() if self.technique is not None else "无" + cultivation_info = self.cultivation_progress.get_detailed_info() + personas_info = ", ".join([p.get_detailed_info() for p in self.personas]) if self.personas else "无" + items_info = ",".join([f"{item.get_detailed_info()}x{quantity}" for item, quantity in self.items.items()]) if self.items else "无" + else: + sect_info = self.sect.get_info() if self.sect is not None else "散修" + region_info = region.get_info() if region is not None else "无" + alignment_info = self.alignment.get_info() + root_info = self.root.get_info() + technique_info = self.technique.get_info() + cultivation_info = self.cultivation_progress.get_info() + personas_info = ", ".join([p.get_info() for p in self.personas]) if self.personas else "无" + items_info = ",".join([f"{item.get_info()}x{quantity}" for item, quantity in self.items.items()]) if self.items else "无" + info += f"sect={sect_info}\n" + info += f"alignment={alignment_info}\n" + info += f"region={region_info}\n" + info += f"root={root_info}\n" + info += f"technique={technique_info}\n" + info += f"cultivation={cultivation_info}\n" + info += f"personas={personas_info}\n" + info += f"items={items_info}\n" + return info def __str__(self) -> str: return self.get_info() @@ -388,24 +425,9 @@ class Avatar: """ 获取角色提示词信息 """ - info = self.get_info() + info = self.get_info(detailed=False) action_space = self.get_action_space_str() - # 构建personas的提示词信息 - personas_prompts = [] - for i, persona in enumerate(self.personas, 1): - personas_prompts.append(f"个性{i}:{persona.prompt}") - personas_info = "\n".join(personas_prompts) - - # 添加灵石信息 - magic_stone_info = f"灵石持有情况:{str(self.magic_stone)}" - - # 添加物品信息 - if self.items: - items_info = "物品持有情况:" + ",".join([f"{item.name}x{quantity}" for item, quantity in self.items.items()]) - else: - items_info = "物品持有情况:无" - # 观测范围内角色(沿用参数名保持兼容) co_region_info = "" if co_region_avatars: @@ -414,16 +436,6 @@ class Avatar: entries.append(f"{other.name}(境界:{other.cultivation_progress.get_simple_info()})") co_region_info = "\n观测范围内角色:" + (",".join(entries) if entries else "无") - # 关系摘要 - 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},驻地:{self.sect.headquarter.name}" - else: # 散修 - sect_info = sect_name - # 历史事件摘要 if self.history_events: history_lines = ";".join([str(e) for e in self.history_events[-8:]]) @@ -431,7 +443,7 @@ class Avatar: else: history_info = "历史事件:无" - 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}" + return f"{info}\n{history_info}\n{co_region_info}\n该角色的目前合法动作为:{action_space}" def get_hover_info(self) -> list[str]: """ diff --git a/src/classes/cultivation.py b/src/classes/cultivation.py index 6201637..4551bc7 100644 --- a/src/classes/cultivation.py +++ b/src/classes/cultivation.py @@ -106,8 +106,8 @@ class CultivationProgress: can_break_through_str = "可以突破" if can_break_through else "不可以突破" return f"{self.realm.value}{self.stage.value}({self.level}级){can_break_through_str}" - def get_simple_info(self) -> str: - return f"{self.realm.value}{self.stage.value}" + def get_detailed_info(self) -> str: + return self.get_info() def get_exp_required(self) -> int: """ diff --git a/src/classes/item.py b/src/classes/item.py index aa63d7b..ff4e1e7 100644 --- a/src/classes/item.py +++ b/src/classes/item.py @@ -19,6 +19,12 @@ class Item: def __str__(self) -> str: return self.name + def get_info(self) -> str: + return f"{self.name} -({self.realm.value})" + + def get_detailed_info(self) -> str: + return f"{self.name} - {self.desc}({self.realm.value})" + def _load_items() -> tuple[dict[int, Item], dict[str, Item]]: """从配表加载item数据""" items_by_id: dict[int, Item] = {} diff --git a/src/classes/magic_stone.py b/src/classes/magic_stone.py index 41d9b3e..db8ce1e 100644 --- a/src/classes/magic_stone.py +++ b/src/classes/magic_stone.py @@ -21,6 +21,12 @@ class MagicStone(int): _upper, _middle, _value = self.exchange() return f"上品灵石:{_upper},中品灵石:{_middle},下品灵石:{_value}" + def get_info(self) -> str: + return str(self) + + def get_detailed_info(self) -> str: + return str(self) + def __add__(self, other: Union['MagicStone', int]) -> 'MagicStone': if isinstance(other, int): return MagicStone(self.value + other) diff --git a/src/classes/mutual_action/conversation.py b/src/classes/mutual_action/conversation.py index d23d913..41784e8 100644 --- a/src/classes/mutual_action/conversation.py +++ b/src/classes/mutual_action/conversation.py @@ -36,10 +36,10 @@ class Conversation(MutualAction): def _build_prompt_infos(self, target_avatar: "Avatar", *, can_into_relation: bool) -> dict: avatar_name_1 = self.avatar.name avatar_name_2 = target_avatar.name - # 目标的 get_prompt_info 已含 personas、关系等,信息更充分 + # 交谈:使用详细信息,便于生成更丰富对话 avatar_infos = { - avatar_name_1: self.avatar.get_prompt_info([]), - avatar_name_2: target_avatar.get_prompt_info([]), + avatar_name_1: self.avatar.get_info(detailed=True), + avatar_name_2: target_avatar.get_info(detailed=True), } # 可能的后天关系(转中文名,给模板阅读) possible_relations = [relation_display_names[r] for r in get_possible_post_relations(self.avatar, target_avatar)] diff --git a/src/classes/mutual_action/mutual_action.py b/src/classes/mutual_action/mutual_action.py index bbf64ae..c43115b 100644 --- a/src/classes/mutual_action/mutual_action.py +++ b/src/classes/mutual_action/mutual_action.py @@ -42,8 +42,8 @@ class MutualAction(DefineAction, LLMAction, TargetingMixin): avatar_name_2 = target_avatar.name # avatar infos 仅放入与两人相关的提示,避免超长 avatar_infos = { - avatar_name_1: self.avatar.cultivation_progress.get_simple_info(), - avatar_name_2: target_avatar.get_prompt_info([]), + avatar_name_1: self.avatar.get_info(detailed=False), + avatar_name_2: target_avatar.get_info(detailed=False), } feedback_actions = self.FEEDBACK_ACTIONS comment = self.COMMENT diff --git a/src/classes/persona.py b/src/classes/persona.py index 190e083..0d9ada8 100644 --- a/src/classes/persona.py +++ b/src/classes/persona.py @@ -23,6 +23,12 @@ class Persona: weight: float condition: str + def get_info(self) -> str: + return self.name + + def get_detailed_info(self) -> str: + return f"{self.name}({self.prompt})" + def _load_personas() -> tuple[dict[int, Persona], dict[str, Persona]]: """从配表加载persona数据""" personas_by_id: dict[int, Persona] = {} diff --git a/src/classes/region.py b/src/classes/region.py index 42cfe04..7c21430 100644 --- a/src/classes/region.py +++ b/src/classes/region.py @@ -168,6 +168,14 @@ class Region(ABC): f"描述: {self.desc}", ] + def get_info(self) -> str: + # 简版:仅返回名称 + return self.name + + def get_detailed_info(self) -> str: + # 基类暂无更多结构化信息,详细版返回名称+描述 + return f"{self.name} - {self.desc}" + class Shape(Enum): """ @@ -245,6 +253,15 @@ class NormalRegion(Region): species_info = self.get_species_info() return f"普通区域:{self.name} - {self.desc} | 物种分布:{species_info}" + def get_info(self) -> str: + return self.name + + def get_detailed_info(self) -> str: + species_info = self.get_species_info() + if not species_info or species_info == "暂无特色物种": + return f"{self.name} - {self.desc}" + 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() @@ -291,6 +308,12 @@ class CultivateRegion(Region): def __str__(self) -> str: return f"修炼区域:{self.name}({self.essence_type}行灵气:{self.essence_density})- {self.desc}" + def get_info(self) -> str: + return self.name + + def get_detailed_info(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) @@ -314,6 +337,12 @@ class CityRegion(Region): # 城市区域暂时仅展示基础信息 return super().get_hover_info() + def get_info(self) -> str: + return self.name + + def get_detailed_info(self) -> str: + return f"{self.name} - {self.desc}" + T = TypeVar('T', NormalRegion, CultivateRegion, CityRegion) diff --git a/src/classes/root.py b/src/classes/root.py index 65166d8..684f7be 100644 --- a/src/classes/root.py +++ b/src/classes/root.py @@ -78,6 +78,12 @@ class Root(_RootMixin, Enum): ), ) + def get_info(self) -> str: + return format_root_cn(self) + + def get_detailed_info(self) -> str: + return self.get_info() + # 元素到灵气类型的一一对应 _essence_by_element = { diff --git a/src/classes/sect.py b/src/classes/sect.py index 4dc3163..72c9651 100644 --- a/src/classes/sect.py +++ b/src/classes/sect.py @@ -41,6 +41,15 @@ class Sect: # 功法:在technique.csv中配置 # TODO:法宝 # TODO:宗内等级和称谓 + + def get_info(self) -> str: + hq = self.headquarter + return f"{self.name}(阵营:{self.alignment},驻地:{hq.name})" + + def get_detailed_info(self) -> str: + # 详细描述:风格、阵营、驻地 + hq = self.headquarter + return f"{self.name}(阵营:{self.alignment},风格:{self.member_act_style},驻地:{hq.name})" def _split_names(value: object) -> list[str]: raw = "" if value is None or str(value) == "nan" else str(value) sep = CONFIG.df.ids_separator diff --git a/src/classes/story_teller.py b/src/classes/story_teller.py index c7fc7e3..a4ccc71 100644 --- a/src/classes/story_teller.py +++ b/src/classes/story_teller.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Dict +from typing import Dict, TYPE_CHECKING from src.utils.config import CONFIG from src.utils.llm import get_prompt_and_call_llm @@ -15,12 +15,12 @@ class StoryTeller: def build_avatar_infos(*avatars: "Avatar") -> Dict[str, str]: """ 将若干角色信息组织为 {name: info} 映射,供故事模板使用。 - 优先使用 `get_prompt_info([])`,失败时退化为 `get_info()`。 + 战斗/小故事使用详细信息。 """ infos: Dict[str, str] = {} for av in avatars: try: - infos[av.name] = av.get_prompt_info([]) + infos[av.name] = av.get_info(detailed=True) except Exception: infos[av.name] = getattr(av, "name", "未知角色") return infos @@ -51,3 +51,8 @@ class StoryTeller: __all__ = ["StoryTeller"] + +if TYPE_CHECKING: + # 仅用于类型检查,避免循环导入 + from src.classes.avatar import Avatar + diff --git a/src/classes/technique.py b/src/classes/technique.py index d4da03d..d5aa1ce 100644 --- a/src/classes/technique.py +++ b/src/classes/technique.py @@ -58,9 +58,13 @@ class Technique: return bool(eval(self.condition, {"__builtins__": {}}, {"avatar": avatar, "Alignment": Alignment})) def get_info(self) -> str: + return f"{self.name}({self.attribute}){self.grade.value}" + + def get_detailed_info(self) -> str: return f"{self.name}({self.attribute}){self.grade.value} {self.prompt}" + # 五行与扩展属性的克制关系 # - 五行:金克木,木克土,土克水,水克火,火克金 # - 雷克邪;邪、冰、风、暗不克任何人 diff --git a/static/game_configs/sect.csv b/static/game_configs/sect.csv index 6de7c44..f9847d4 100644 --- a/static/game_configs/sect.csv +++ b/static/game_configs/sect.csv @@ -1,5 +1,11 @@ id,name,desc,member_act_style,alignment,sect_surnames,male_sect_given_names,female_sect_given_names ,,宗门名称与描述,宗门成员行事风格,阵营(正/中/邪),宗门常用姓氏(分号分隔),男性常用名(分号分隔),女性常用名(分号分隔) 1,明心剑宗,通玄界东方第一宗,以无上剑道称雄于世。云纹禁制为不传心法。,清明克己,行止如一。重剑与心法并重,讲究明心见性。,正,明;灵;清,阁;松;德;吉;和;澜;彦;珣;智;海;泉,如;玑;碧;清霁;素心;明珑;玄音;澄如;玉衡 +2,百兽宗,以驯养灵兽闻名,豢养各种妖兽灵怪为战力。,你言语直接,重视力量与血性,崇尚狩猎与搏斗。,邪,,驼王;飞熊;虎魄;狼行;熊罡;白猿;石坚;山岚;青鬃;玄爪,狐绮;白貂;青翎;雪牙;赤羽;玄狸;灵爪;月狐 +3,水镜宗,正道十宗之一,实则严守中立。拥有仙界异宝"彻天水镜"可预知未来。,你处事冷静圆融,喜以柔克刚,擅借力与反制。,中,水;镜;颜;玉;寒;霜;冰;清;沐;阮,岚;照心;寒江,水月;映月;寒影;秋水;轻漪;雪落;如镜;青荷;凝霜 4,冥王宗,行走幽冥之道,术法阴冷狠厉。,你言辞冷厉少情,敬畏因果而不惧杀伐,偏向效率与结果。,邪,宋;元;冥;王;玄;幽;夜;白;江;冷,元敕;元难;元烁;冥焰;噬魂;夜阙;幽垣;玄骨;寒魄;冥狱;影灭;夜行,冥霜;幽绫;夜珑;寒鸢;阎铃;魇瑶;玄魄;幽棂 +5,朱勾宗,邪宗大派。以炼器、机关、暗杀闻名于世,素来阴毒冷僻。,你直面欲望与代价,不惧黑暗,以攻伐见长。,邪,朱;血;狱;百;,血手;勾魂;朱砂;赤狱;凝血;摄魄;夺心;吞灵;渊渟;夜烬,朱绫;夜鸢;绯刃;寒簪;明玥;凝芒;血莹;玉珥 6,合欢宗,以情入道,双修与魅术并重,善驭人心,长于权变。,你辞令婉转,善于拿捏人欲与局势,以柔制刚。,中,合;欢;苏;陆;柳;花;月;楚;顾;白,流烟,婉心;轻柔;疏影;如梦;绮念;月华;惜香;慕雪;倾城 +7,镇魂宗,铁血风格,擅安魂、封邪、渡厄,兼有刚烈镇压之术。,你肃穆沉稳,重安魂镇邪,少言而果决。,正,厉;卢;镇;魂;钟;青;凌;白;楚;顾,斗量;阳;镇灵;定魄;钟离;安魂;肃霜;白岭;清钟;涤秽;正鸣;宁川,清宁;素铃;靖霜;澄心;灵钟;镇月;安祈;涤魂 +8,幽魂噬影宗,镇宗典籍《幽冥录》。幽明气为根基。,你行事隐秘果断,重结果轻虚名,擅潜行与出其不意。,邪,冥;阎;鬼;百;幽;归;应;阴;碧;夜,璃;无藏;馑;噬影;隐魄;夜藏;无相;玄影;摄魂;遁形;寒星;绝响;空痕,采儿;幽姝;冥绮;寒灯;影绫;夜绡;魇歌;暗萝 +9,千帆城,炼器大宗,巧匠云集。著名法宝有灵灭丝、定魂蓝星、天罗网、万里极光壁、飞翼等。商旅云集,自成体系。,你务实精明,重交易与信誉,崇尚规则与秩序。,中,商;楚;顾;白;苏;林;叶;秦;赵;魏,商行;持衡;清评;问价;立契;通衡;问道;理市;衡准;守约,素蓝;明衡;巧心;青帆;绫舟;观星;衡绫;星槎