From a038d329044f1d2112e401773ccbdec71e7a95c1 Mon Sep 17 00:00:00 2001 From: bridge Date: Thu, 16 Oct 2025 00:54:34 +0800 Subject: [PATCH] update battle --- src/classes/action/battle.py | 6 ++++- src/classes/avatar.py | 2 ++ src/classes/battle.py | 22 +++++++++---------- src/classes/mutual_action/attack.py | 2 +- src/classes/mutual_action/conversation.py | 2 +- src/classes/mutual_action/drive_away.py | 2 +- src/classes/mutual_action/dual_cultivation.py | 4 ++-- src/classes/mutual_action/mutual_action.py | 2 +- src/classes/story_teller.py | 4 ++-- static/config.yml | 2 +- static/game_configs/persona.csv | 4 ++-- 11 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/classes/action/battle.py b/src/classes/action/battle.py index ea974c8..3a647db 100644 --- a/src/classes/action/battle.py +++ b/src/classes/action/battle.py @@ -10,6 +10,10 @@ class Battle(InstantAction): COMMENT = "与目标进行对战,判定胜负" DOABLES_REQUIREMENTS = "任何时候都可以执行" PARAMS = {"avatar_name": "AvatarName"} + # 提供用于故事生成的提示词:不出现血量/伤害等数值描述 + STORY_PROMPT: str | None = ( + "不要出现具体血量、伤害点数或任何数值表达。" + ) def _get_target(self, avatar_name: str): for v in self.world.avatar_manager.avatars.values(): @@ -57,7 +61,7 @@ class Battle(InstantAction): target = self._get_target(avatar_name) avatar_infos = StoryTeller.build_avatar_infos(self.avatar, target) start_text = getattr(self, "_start_event_content", "") or result_event.content - story = StoryTeller.tell_story(avatar_infos, start_text, result_event.content) + story = StoryTeller.tell_story(avatar_infos, start_text, result_event.content, self.STORY_PROMPT) story_event = Event(self.world.month_stamp, story) return [result_event, story_event] diff --git a/src/classes/avatar.py b/src/classes/avatar.py index 6e69970..ee034ad 100644 --- a/src/classes/avatar.py +++ b/src/classes/avatar.py @@ -32,6 +32,7 @@ from src.classes.alignment import Alignment from src.utils.params import filter_kwargs_for_callable from src.classes.sect import Sect from src.classes.appearance import Appearance, get_random_appearance +from src.classes.battle import get_base_strength persona_num = CONFIG.avatar.persona_num @@ -476,6 +477,7 @@ class Avatar: f"境界: {str(self.cultivation_progress)}", f"HP: {self.hp}", f"MP: {self.mp}", + f"战斗力: {int(get_base_strength(self))}", ] lines.append(f"宗门: {self.get_sect_str()}") from src.classes.root import format_root_cn diff --git a/src/classes/battle.py b/src/classes/battle.py index 9ba9bd0..5d59b6b 100644 --- a/src/classes/battle.py +++ b/src/classes/battle.py @@ -26,29 +26,29 @@ _MIN_RATIO: float = 1.05 # 最小相对优势比,确保赢 _PAIR_BIAS: float = 1.1 # 成对偏置:让败者再多一点、赢家再少一点 -def _combat_strength_vs(opponent: "Avatar", self_avatar: "Avatar") -> float: +def get_base_strength(self_avatar: "Avatar") -> float: """ - 计算对某个对手的有效战斗力: - = 10×ln(1+修为等级) + 品阶点数(0/3/6) + 克制点数(若克制则+3) - 说明: - - 修为使用总等级(1..120)并做对数缩放,避免过大; - - 品阶加点为线性,避免与修为重复放大; - - 克制只在“对某个对手”时生效,因此放在此函数处理。 + 基础战斗力:与对手无关。 + = 10×ln(1+修为等级) + 品阶点数(0/3/6) """ level = max(1, self_avatar.cultivation_progress.level) strength_from_level = _STRENGTH_LOG_SCALE * math.log1p(level) - grade_points = 0.0 if self_avatar.technique is not None: grade_points = _GRADE_POINTS.get(self_avatar.technique.grade, 0.0) + return strength_from_level + grade_points + +def _combat_strength_vs(opponent: "Avatar", self_avatar: "Avatar") -> float: + """ + 相对战斗力:= 基础战斗力 + 克制点数(若克制则+3) + """ + base = get_base_strength(self_avatar) suppression_points = 0.0 if self_avatar.technique is not None and opponent.technique is not None: - # 仅需“是否克制”的布尔,不引入倍率。 if get_suppression_bonus(self_avatar.technique.attribute, opponent.technique.attribute) > 0.0: suppression_points = _SUPPRESSION_POINTS - - return strength_from_level + grade_points + suppression_points + return base + suppression_points def _strength_diff(attacker: "Avatar", defender: "Avatar") -> float: diff --git a/src/classes/mutual_action/attack.py b/src/classes/mutual_action/attack.py index 78aba8d..c18f765 100644 --- a/src/classes/mutual_action/attack.py +++ b/src/classes/mutual_action/attack.py @@ -11,7 +11,7 @@ class Attack(MutualAction): DOABLES_REQUIREMENTS = "与目标处于同一区域" PARAMS = {"target_avatar": "AvatarName"} FEEDBACK_ACTIONS = ["Escape", "Battle"] - story_prompt: str = "" + STORY_PROMPT: str = "" def _settle_feedback(self, target_avatar: "Avatar", feedback_name: str) -> None: fb = str(feedback_name).strip() diff --git a/src/classes/mutual_action/conversation.py b/src/classes/mutual_action/conversation.py index 09cd435..abfac27 100644 --- a/src/classes/mutual_action/conversation.py +++ b/src/classes/mutual_action/conversation.py @@ -28,7 +28,7 @@ class Conversation(MutualAction): DOABLES_REQUIREMENTS = "与目标处于同一区域" PARAMS = {"target_avatar": "AvatarName"} FEEDBACK_ACTIONS: list[str] = ["Talk", "Reject"] - story_prompt: str = "" + STORY_PROMPT: str = "" def _get_template_path(self) -> Path: # 使用 talk.txt 模板,以获取是否接受与对话内容 diff --git a/src/classes/mutual_action/drive_away.py b/src/classes/mutual_action/drive_away.py index 0de00d1..673acbb 100644 --- a/src/classes/mutual_action/drive_away.py +++ b/src/classes/mutual_action/drive_away.py @@ -11,7 +11,7 @@ class DriveAway(MutualAction): DOABLES_REQUIREMENTS = "与目标处于同一区域" PARAMS = {"target_avatar": "AvatarName"} FEEDBACK_ACTIONS = ["MoveAwayFromRegion", "Battle"] - story_prompt: str = "" + STORY_PROMPT: str = "" def _settle_feedback(self, target_avatar: "Avatar", feedback_name: str) -> None: fb = str(feedback_name).strip() diff --git a/src/classes/mutual_action/dual_cultivation.py b/src/classes/mutual_action/dual_cultivation.py index 34dc5ca..7154963 100644 --- a/src/classes/mutual_action/dual_cultivation.py +++ b/src/classes/mutual_action/dual_cultivation.py @@ -29,7 +29,7 @@ class DualCultivation(MutualAction): PARAMS = {"target_avatar": "AvatarName"} FEEDBACK_ACTIONS = ["Accept", "Reject"] # 提供用于故事生成的提示词,供 StoryTeller 模板参考 - story_prompt: str | None = "两位修士在双修过程中情愫暗生,以含蓄、雅致的文字描绘一段暧昧而不露骨的双修体验,体现彼此性格、境界差异与甜蜜的恋爱时光。" + STORY_PROMPT: str | None = "两位修士在双修过程中情愫暗生,以含蓄、雅致的文字描绘一段暧昧而不露骨的双修体验,体现彼此性格、境界差异与甜蜜的恋爱时光。不要体现经验的数值。" def _get_template_path(self) -> Path: # 复用 mutual_action 模板,仅需返回 Accept/Reject @@ -104,7 +104,7 @@ class DualCultivation(MutualAction): # 生成恋爱/双修小故事:使用通用故事模板 avatar_infos = StoryTeller.build_avatar_infos(self.avatar, target) start_text = self._start_event_content or result_event.content - story = StoryTeller.tell_story(avatar_infos, start_text, result_event.content, self.story_prompt) + story = StoryTeller.tell_story(avatar_infos, start_text, result_event.content, self.STORY_PROMPT) story_event = Event(self.world.month_stamp, story) events.append(story_event) else: diff --git a/src/classes/mutual_action/mutual_action.py b/src/classes/mutual_action/mutual_action.py index 465aea2..01384b1 100644 --- a/src/classes/mutual_action/mutual_action.py +++ b/src/classes/mutual_action/mutual_action.py @@ -43,7 +43,7 @@ class MutualAction(DefineAction, LLMAction, TargetingMixin): "Battle": "战斗", } # 若该互动动作可能生成小故事,可在子类中覆盖该提示词 - story_prompt: str | None = None + STORY_PROMPT: str | None = None def _get_template_path(self) -> Path: return CONFIG.paths.templates / "mutual_action.txt" diff --git a/src/classes/story_teller.py b/src/classes/story_teller.py index 70d9a8f..02b906d 100644 --- a/src/classes/story_teller.py +++ b/src/classes/story_teller.py @@ -42,7 +42,7 @@ class StoryTeller: return infos @staticmethod - def tell_story(avatar_infos: Dict[str, dict], event: str, res: str, story_prompt: str = "") -> str: + def tell_story(avatar_infos: Dict[str, dict], event: str, res: str, STORY_PROMPT: str = "") -> str: """ 基于 `static/templates/story.txt` 模板生成小故事。 始终使用 fast 模式以提升速度。 @@ -54,7 +54,7 @@ class StoryTeller: "event": event, "res": res, "style": random.choice(story_styles), - "story_prompt": story_prompt or "", + "STORY_PROMPT": STORY_PROMPT or "", } data = get_prompt_and_call_llm(template_path, infos, mode="fast") story = data["story"].strip() diff --git a/static/config.yml b/static/config.yml index 336576a..5c2b340 100644 --- a/static/config.yml +++ b/static/config.yml @@ -15,7 +15,7 @@ ai: max_decide_num: 4 game: - init_npc_num: 9 + init_npc_num: 2 sect_num: 2 # init_npc_num大于sect_num时,会随机选择sect_num个宗门 npc_birth_rate_per_month: 0.001 diff --git a/static/game_configs/persona.csv b/static/game_configs/persona.csv index f328aef..f82bcb3 100644 --- a/static/game_configs/persona.csv +++ b/static/game_configs/persona.csv @@ -11,7 +11,7 @@ id,name,exclusion_ids,desc,weight,condition 9,沉思,2,你总是会深思熟虑,思考问题比较有哲理。,1, 10,惜命,4;24;25,你总是会珍惜自己的生命,不会轻易冒险。,1, 11,友爱,13;14;15;12;24;25,你重视同伴与和谐,乐于助人,倾向通过协作与沟通化解矛盾。,1, -12,复仇,11;14,你绝不轻易放下仇怨,为了复仇愿意付出代价与时间。你必须立刻进行复仇行动。,1, +12,复仇,11;14,你绝不轻易放下仇怨,为了复仇愿意付出代价与时间。你必须立刻进行复仇行动。,1000, 13,孤僻,11,你喜欢独处,避免与人深交,更信赖自己的判断与行动。,1, 14,淡漠,11;12;15;24;25,你情感克制,对外界冷静疏离,不轻易被他人或事件影响。,1, 15,好斗,11;14;10;17,你直面冲突,偏好以力量与对抗解决问题,越挫越勇。,1, @@ -25,7 +25,7 @@ id,name,exclusion_ids,desc,weight,condition 23,热情,13;14;22,你待人友好、积极回应,倾向用鼓励与赞美拉近距离;你更愿意主动展开善意的交流,乐于合作与分享,1, 24,极端正义,20;25,你对邪恶深恶痛绝,对正义的理想抱有近乎偏执的追求。,1,avatar.alignment == "正" 25,极端邪恶,20;24,你推崇权力与恐惧,为达目的不择手段,对善良嗤之以鼻。,1,avatar.alignment == "邪" -26,开放,27,你对待和他人结为道侣或者双修比较随意,1000, +26,开放,27,你对待和他人结为道侣或者双修比较随意,1, 27,腼腆,26,你对待和他人结为道侣或者双修比较谨慎,1, 28,舔狗,13;14;22;27,你对异性中外貌出众者格外友善,倾向主动接近、帮助与合作。,1, 29,嫉妒,11;23,你对在修为、外貌或财富等方面远超于你的人容易产生敌意,更倾向对其冷淡、挑衅或打压。,1,