add kill and grab
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from src.classes.action import InstantAction
|
||||
from src.classes.event import Event
|
||||
@@ -6,6 +7,83 @@ from src.classes.battle import decide_battle, get_effective_strength_pair
|
||||
from src.classes.story_teller import StoryTeller
|
||||
from src.classes.normalize import normalize_avatar_name
|
||||
from src.classes.death import handle_death
|
||||
from src.classes.equipment_grade import EquipmentGrade
|
||||
from src.classes.single_choice import make_decision
|
||||
import random
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
from src.classes.weapon import Weapon
|
||||
from src.classes.auxiliary import Auxiliary
|
||||
|
||||
|
||||
async def handle_loot(winner: Avatar, loser: Avatar) -> str:
|
||||
"""
|
||||
处理杀人夺宝逻辑
|
||||
|
||||
Args:
|
||||
winner: 胜利者
|
||||
loser: 失败者(已死亡)
|
||||
|
||||
Returns:
|
||||
str: 夺宝结果描述文本(如"并夺取了..."),如果没有夺取则为空字符串
|
||||
"""
|
||||
loot_candidates = []
|
||||
|
||||
# 检查兵器
|
||||
if loser.weapon and loser.weapon.grade != EquipmentGrade.COMMON:
|
||||
loot_candidates.append(("weapon", loser.weapon))
|
||||
|
||||
# 检查辅助装备
|
||||
if loser.auxiliary and loser.auxiliary.grade != EquipmentGrade.COMMON:
|
||||
loot_candidates.append(("auxiliary", loser.auxiliary))
|
||||
|
||||
if not loot_candidates:
|
||||
return ""
|
||||
|
||||
# 优先选法宝,其次宝物;如果有多个同级,随机选一个
|
||||
loot_candidates.sort(key=lambda x: 1 if x[1].grade == EquipmentGrade.ARTIFACT else 0, reverse=True)
|
||||
# 筛选出最高优先级的那些
|
||||
best_grade = loot_candidates[0][1].grade
|
||||
best_candidates = [c for c in loot_candidates if c[1].grade == best_grade]
|
||||
loot_type, loot_item = random.choice(best_candidates)
|
||||
|
||||
should_loot = False
|
||||
|
||||
# 判定是否夺取
|
||||
# 1. 如果winner当前部位为空或为凡品,直接夺取
|
||||
winner_current = getattr(winner, loot_type)
|
||||
if winner_current is None or winner_current.grade == EquipmentGrade.COMMON:
|
||||
should_loot = True
|
||||
else:
|
||||
# 2. 否则让 AI 决策
|
||||
context = f"战斗胜利,{loser.name} 身死道消,留下了一件{loot_item.grade.value}{'兵器' if loot_type == 'weapon' else '辅助装备'}『{loot_item.name}』({loot_item.desc})。"
|
||||
options = [
|
||||
{
|
||||
"key": "A",
|
||||
"desc": f"夺取{loot_item.grade.value}『{loot_item.name}』({loot_item.desc}),替换掉身上的『{winner_current.name}』({winner_current.grade.value},{winner_current.desc})。"
|
||||
},
|
||||
{
|
||||
"key": "B",
|
||||
"desc": f"放弃『{loot_item.name}』,保留身上的『{winner_current.name}』。"
|
||||
}
|
||||
]
|
||||
choice = await make_decision(winner, context, options)
|
||||
if choice == "A":
|
||||
should_loot = True
|
||||
|
||||
if should_loot:
|
||||
if loot_type == "weapon":
|
||||
winner.change_weapon(loot_item)
|
||||
from src.classes.weapon import get_common_weapon
|
||||
loser.change_weapon(get_common_weapon(loot_item.weapon_type)) # 给死者塞个凡品防止空指针
|
||||
else:
|
||||
winner.change_auxiliary(loot_item)
|
||||
loser.change_auxiliary(None)
|
||||
|
||||
return f"并夺取了对方的{loot_item.grade.value}『{loot_item.name}』!"
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
class Battle(InstantAction):
|
||||
@@ -83,6 +161,11 @@ class Battle(InstantAction):
|
||||
is_fatal = loser.hp <= 0
|
||||
if is_fatal:
|
||||
result_text = f"{winner.name} 战胜了 {loser.name},造成{loser_damage}点伤害。{loser.name} 遭受重创,当场陨落。"
|
||||
|
||||
# 杀人夺宝
|
||||
loot_text = await handle_loot(winner, loser)
|
||||
result_text += loot_text
|
||||
|
||||
else:
|
||||
result_text = f"{winner.name} 战胜了 {loser.name},{loser.name} 受伤{loser_damage}点,{winner.name} 也受伤{winner_damage}点"
|
||||
|
||||
|
||||
@@ -61,5 +61,5 @@ alignment_strs = {
|
||||
alignment_infos = {
|
||||
Alignment.RIGHTEOUS: "正义阵营的理念是:扶助弱小,维护秩序,除魔卫道。",
|
||||
Alignment.NEUTRAL: "中立阵营的理念是:顺势而为,趋利避害,重视自度与平衡,不轻易站队。",
|
||||
Alignment.EVIL: "邪恶阵营的理念是:弱肉强食,以自身利益为先,蔑视规则,推崇权力与恐惧。",
|
||||
Alignment.EVIL: "邪恶阵营的理念是:弱肉强食,以自身利益为先,蔑视规则,推崇权力与恐惧。行事狠辣,常有杀人夺宝之举。",
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any, Dict, List, TYPE_CHECKING
|
||||
from src.utils.llm import call_llm_with_template
|
||||
from src.classes.avatar import Avatar
|
||||
from src.utils.config import CONFIG
|
||||
import json
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
async def make_decision(
|
||||
avatar: Avatar,
|
||||
avatar: "Avatar",
|
||||
context_desc: str,
|
||||
options: List[Dict[str, Any]]
|
||||
) -> str:
|
||||
@@ -57,11 +59,21 @@ async def make_decision(
|
||||
except (json.JSONDecodeError, ValueError):
|
||||
# 如果 JSON 解析失败,直接看字符串内容是否就是选项 key
|
||||
choice = clean_result
|
||||
# 有时候 llm 会输出 "choice: A",这里做个兼容
|
||||
else:
|
||||
choice = clean_result
|
||||
|
||||
# 验证 choice 是否在 options key 中
|
||||
valid_keys = {opt["key"] for opt in options}
|
||||
assert choice in valid_keys, f"choice {choice} not in valid_keys {valid_keys}"
|
||||
# 简单的容错:如果返回的是 "A." 或者 "A "
|
||||
if choice not in valid_keys:
|
||||
for k in valid_keys:
|
||||
if k in choice:
|
||||
choice = k
|
||||
break
|
||||
|
||||
if choice not in valid_keys:
|
||||
# 兜底:默认选第一个
|
||||
choice = options[0]["key"]
|
||||
|
||||
return choice
|
||||
|
||||
|
||||
Reference in New Issue
Block a user