add choice helper
This commit is contained in:
@@ -25,13 +25,11 @@ class Auxiliary:
|
||||
# 特殊属性(用于存储实例特定数据)
|
||||
special_data: dict = field(default_factory=dict)
|
||||
|
||||
def get_info(self) -> str:
|
||||
"""获取简略信息"""
|
||||
suffix = ""
|
||||
# 万魂幡特殊显示
|
||||
if self.name == "万魂幡" and self.special_data.get("devoured_souls", 0) > 0:
|
||||
suffix = f"(吞噬魂魄:{self.special_data['devoured_souls']})"
|
||||
return f"{self.name}{suffix}"
|
||||
def get_info(self, detailed: bool = False) -> str:
|
||||
"""获取信息"""
|
||||
if detailed:
|
||||
return self.get_detailed_info()
|
||||
return f"{self.name}"
|
||||
|
||||
def get_detailed_info(self) -> str:
|
||||
"""获取详细信息"""
|
||||
|
||||
@@ -150,7 +150,7 @@ def _find_potential_master(avatar: Avatar) -> Optional[Avatar]:
|
||||
|
||||
|
||||
def _can_get_weapon(avatar: Avatar) -> bool:
|
||||
"""检查是否可以获得兵器奇遇:当前兵器是练气级(凡品)时可触发"""
|
||||
"""检查是否可以获得兵器奇遇:当前兵器是练气级(练气)时可触发"""
|
||||
if avatar.weapon is None:
|
||||
return True
|
||||
return avatar.weapon.realm == Realm.Qi_Refinement
|
||||
@@ -395,7 +395,7 @@ async def try_trigger_fortune(avatar: Avatar) -> list[Event]:
|
||||
|
||||
|
||||
# 导入单选决策模块
|
||||
from src.classes.single_choice import make_decision
|
||||
from src.classes.single_choice import make_decision, format_swap_choice_desc
|
||||
|
||||
async def _resolve_choice(
|
||||
new_obj: Any,
|
||||
@@ -414,16 +414,17 @@ async def try_trigger_fortune(avatar: Avatar) -> list[Event]:
|
||||
return True, f"{avatar.name} 获得{new_grade_val}{type_label}『{new_name}』"
|
||||
|
||||
old_name = old_obj.name
|
||||
old_grade_val = getattr(old_obj, "grade", getattr(old_obj, "realm", None)).value
|
||||
|
||||
swap_desc = format_swap_choice_desc(new_obj, old_obj, type_label)
|
||||
|
||||
options = [
|
||||
{
|
||||
"key": "A",
|
||||
"desc": f"保留原{type_label}『{old_name}』({old_grade_val}),放弃新{type_label}『{new_name}』({new_grade_val})。"
|
||||
"desc": f"保留原{type_label}『{old_name}』,放弃新{type_label}『{new_name}』。"
|
||||
},
|
||||
{
|
||||
"key": "B",
|
||||
"desc": f"卖掉原{type_label}『{old_name}』换取灵石,接受新{type_label}『{new_name}』({new_grade_val})。"
|
||||
"desc": f"卖掉原{type_label}『{old_name}』换取灵石,接受新{type_label}『{new_name}』。\n{swap_desc}"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
import random
|
||||
|
||||
from src.classes.single_choice import make_decision
|
||||
from src.classes.single_choice import make_decision, format_swap_choice_desc
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
@@ -49,14 +49,15 @@ async def kill_and_grab(winner: Avatar, loser: Avatar) -> str:
|
||||
else:
|
||||
# 其他情况下都让 AI 决策
|
||||
# 构建详细描述,包含效果
|
||||
item_desc = loot_item.get_detailed_info()
|
||||
current_desc = winner_current.get_detailed_info()
|
||||
|
||||
context = f"战斗胜利,{loser.name} 身死道消,留下了一件{loot_item.realm.value}{'兵器' if loot_type == 'weapon' else '辅助装备'}『{item_desc}』。"
|
||||
item_label = '兵器' if loot_type == 'weapon' else '辅助装备'
|
||||
context = f"战斗胜利,{loser.name} 身死道消,留下了一件{loot_item.realm.value}{item_label}『{loot_item.name}』。"
|
||||
|
||||
swap_desc = format_swap_choice_desc(loot_item, winner_current, item_label)
|
||||
|
||||
options = [
|
||||
{
|
||||
"key": "A",
|
||||
"desc": f"夺取『{loot_item.name}』,卖掉身上的『{winner_current.name}』换取灵石。\n - 新装备:{item_desc}\n - 原装备:{current_desc}"
|
||||
"desc": f"夺取『{loot_item.name}』,卖掉身上的『{winner_current.name}』换取灵石。\n{swap_desc}"
|
||||
},
|
||||
{
|
||||
"key": "B",
|
||||
|
||||
@@ -80,3 +80,25 @@ async def make_decision(
|
||||
choice = options[0]["key"]
|
||||
|
||||
return choice
|
||||
|
||||
|
||||
def format_swap_choice_desc(new_item: Any, old_item: Any | None, item_type_name: str) -> str:
|
||||
"""
|
||||
生成替换装备/功法时的决策描述文本。
|
||||
|
||||
Args:
|
||||
new_item: 新获得的物品对象(必须实现 get_info(detailed=True))
|
||||
old_item: 当前持有的物品对象(可能为 None)
|
||||
item_type_name: 物品类型名称(如"兵器"、"功法")
|
||||
"""
|
||||
new_info = item.get_info(detailed=True)
|
||||
|
||||
if old_item:
|
||||
old_info = item.get_info(detailed=True)
|
||||
return (
|
||||
f"现有{item_type_name}:{old_info}\n"
|
||||
f"新{item_type_name}:{new_info}\n"
|
||||
f"(选择替换将卖出旧{item_type_name})"
|
||||
)
|
||||
else:
|
||||
return f"新{item_type_name}:{new_info}"
|
||||
@@ -73,7 +73,9 @@ class Technique:
|
||||
return True
|
||||
return bool(eval(self.condition, {"__builtins__": {}}, {"avatar": avatar, "Alignment": Alignment}))
|
||||
|
||||
def get_info(self) -> str:
|
||||
def get_info(self, detailed: bool = False) -> str:
|
||||
if detailed:
|
||||
return self.get_detailed_info()
|
||||
return f"{self.name}({self.attribute}){self.grade.value}"
|
||||
|
||||
def get_detailed_info(self) -> str:
|
||||
|
||||
@@ -30,8 +30,10 @@ class Weapon:
|
||||
# 特殊属性(如万魂幡的吞噬魂魄计数)
|
||||
special_data: dict = field(default_factory=dict)
|
||||
|
||||
def get_info(self) -> str:
|
||||
"""获取简略信息"""
|
||||
def get_info(self, detailed: bool = False) -> str:
|
||||
"""获取信息"""
|
||||
if detailed:
|
||||
return self.get_detailed_info()
|
||||
return f"{self.name}"
|
||||
|
||||
def get_detailed_info(self) -> str:
|
||||
|
||||
@@ -155,7 +155,7 @@ protagonist_configs = [
|
||||
"level": 65,
|
||||
"sect": 14, # 噬魔宗
|
||||
"technique": 28, # 燃血大法 (自残修仙)
|
||||
"weapon": 1001, # 凡品剑 (红中)
|
||||
"weapon": 1001, # 练气剑 (红中)
|
||||
"auxiliary": 2008, # 菩提子 (清心压制)
|
||||
"personas": ["无常", "好斗", "忠诚"],
|
||||
"appearance": 20,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
id,name,weapon_type,grade,desc,effects
|
||||
,名称,兵器类型,等级(练气/筑基/金丹/元婴),描述/提示词,JSON形式(支持宽松格式,见effects.py说明)
|
||||
1001,凡品剑,剑,练气,市井铁匠铺打造的铁剑,勉强能用。,{extra_battle_strength_points: 1}
|
||||
1002,凡品刀,刀,练气,厚背砍刀,寻常武夫的最爱。,{extra_battle_strength_points: 1}
|
||||
1003,凡品枪,枪,练气,白蜡杆制成,枪头挂着红缨。,{extra_battle_strength_points: 1}
|
||||
1004,凡品棍,棍,练气,普通的硬木棍,长与眉齐。,{extra_battle_strength_points: 1}
|
||||
1005,凡品扇,扇,练气,文人雅士常用的折扇,附庸风雅。,{extra_battle_strength_points: 1}
|
||||
1006,凡品鞭,鞭,练气,普通的皮鞭,多用于赶车或刑罚。,{extra_battle_strength_points: 1}
|
||||
1007,凡品琴,琴,练气,桐木制成的古琴,音色尚可。,{extra_battle_strength_points: 1}
|
||||
1008,凡品笛,笛,练气,紫竹削制,声音清脆。,{extra_battle_strength_points: 1}
|
||||
1009,凡品暗器,暗器,练气,随处可见的铁制暗器。,{extra_battle_strength_points: 1}
|
||||
1001,练气剑,剑,练气,市井铁匠铺打造的铁剑,勉强能用。,{extra_battle_strength_points: 1}
|
||||
1002,练气刀,刀,练气,厚背砍刀,寻常武夫的最爱。,{extra_battle_strength_points: 1}
|
||||
1003,练气枪,枪,练气,白蜡杆制成,枪头挂着红缨。,{extra_battle_strength_points: 1}
|
||||
1004,练气棍,棍,练气,普通的硬木棍,长与眉齐。,{extra_battle_strength_points: 1}
|
||||
1005,练气扇,扇,练气,文人雅士常用的折扇,附庸风雅。,{extra_battle_strength_points: 1}
|
||||
1006,练气鞭,鞭,练气,普通的皮鞭,多用于赶车或刑罚。,{extra_battle_strength_points: 1}
|
||||
1007,练气琴,琴,练气,桐木制成的古琴,音色尚可。,{extra_battle_strength_points: 1}
|
||||
1008,练气笛,笛,练气,紫竹削制,声音清脆。,{extra_battle_strength_points: 1}
|
||||
1009,练气暗器,暗器,练气,随处可见的铁制暗器。,{extra_battle_strength_points: 1}
|
||||
2001,青霜剑,剑,筑基,剑气森寒。,{extra_battle_strength_points: 2}
|
||||
2002,井中月,刀,筑基,刀光如井中映月,虚实难测。,{extra_battle_strength_points: 2}
|
||||
2003,火尖枪,枪,筑基,枪头隐有火光,能引动凡火。,"{extra_battle_strength_points: 2, extra_max_hp: 50}"
|
||||
|
||||
|
@@ -49,7 +49,7 @@ def dummy_avatar(base_world):
|
||||
|
||||
# 赋予一个 Mock 武器,防止 get_avatar_info 报错
|
||||
av.weapon = MagicMock()
|
||||
av.weapon.get_detailed_info.return_value = "测试木剑(凡品)"
|
||||
av.weapon.get_detailed_info.return_value = "测试木剑(练气)"
|
||||
av.weapon_proficiency = 0.0
|
||||
|
||||
return av
|
||||
|
||||
@@ -82,35 +82,6 @@ class TestEquipment:
|
||||
assert aux.name in detailed
|
||||
assert aux.realm.value in detailed
|
||||
|
||||
def test_soul_banner(self):
|
||||
"""测试万魂幡特殊逻辑"""
|
||||
# 查找万魂幡
|
||||
soul_banner = None
|
||||
for a in auxiliaries_by_id.values():
|
||||
if a.name == "万魂幡":
|
||||
soul_banner = a
|
||||
break
|
||||
|
||||
if not soul_banner:
|
||||
pytest.skip("万魂幡 not found in config")
|
||||
|
||||
import copy
|
||||
banner = copy.deepcopy(soul_banner)
|
||||
|
||||
# 初始状态
|
||||
assert "吞噬魂魄" not in banner.get_info()
|
||||
|
||||
# 增加魂魄
|
||||
banner.special_data["devoured_souls"] = 100
|
||||
|
||||
# 检查显示更新
|
||||
assert "吞噬魂魄:100" in banner.get_info()
|
||||
assert "吞噬魂魄:100" in banner.get_detailed_info()
|
||||
|
||||
# 检查结构化信息
|
||||
struct = banner.get_structured_info()
|
||||
assert "已吞噬魂魄:100" in struct["desc"]
|
||||
|
||||
def test_grade_renaming_compatibility(self):
|
||||
"""测试 realm 改名后的兼容性(如果有必要)"""
|
||||
# 确保 weapon 和 auxiliary 确实有 realm 属性
|
||||
|
||||
Reference in New Issue
Block a user