add protagonist

This commit is contained in:
bridge
2025-12-13 20:48:03 +08:00
parent 1083ec3db6
commit 9ed511aafb
3 changed files with 54 additions and 7 deletions

View File

@@ -18,7 +18,7 @@ from src.sim.simulator import Simulator
from src.classes.world import World
from src.classes.calendar import Month, Year, create_month_stamp
from src.run.load_map import load_cultivation_world_map
from src.sim.new_avatar import make_avatars as _new_make, create_avatar_from_request
from src.sim.new_avatar import make_avatars as _new_make_random, create_avatar_from_request
from src.utils.config import CONFIG
from src.classes.sect import sects_by_id
from src.classes.technique import techniques_by_id
@@ -34,6 +34,7 @@ from src.classes.celestial_phenomenon import celestial_phenomena_by_id
from src.classes.long_term_objective import set_user_long_term_objective, clear_user_long_term_objective
from src.sim.save.save_game import save_game, list_saves
from src.sim.load.load_game import load_game
from src.utils import protagonist as prot_utils
import random
# 全局游戏实例
@@ -225,9 +226,40 @@ def init_game():
existed_sects = pool[:needed_sects]
# 创建角色
# 注意:这里直接调用 new_avatar 的 make_avatars避免循环导入
all_avatars = _new_make(world, count=CONFIG.game.init_npc_num, current_month_stamp=world.month_stamp, existed_sects=existed_sects)
world.avatar_manager.avatars.update(all_avatars)
protagonist_mode = getattr(CONFIG.avatar, "protagonist", "none")
target_total_count = int(getattr(CONFIG.game, "init_npc_num", 12))
final_avatars = {}
# 1. 生成主角 (All / Random)
spawned_protagonists_count = 0
if protagonist_mode in ["all", "random"]:
prob = 1.0 if protagonist_mode == "all" else 0.05
# 注意spawn_protagonists 返回的是 dict
prot_avatars = prot_utils.spawn_protagonists(world, world.month_stamp, probability=prob)
final_avatars.update(prot_avatars)
spawned_protagonists_count = len(prot_avatars)
print(f"生成了 {spawned_protagonists_count} 位主角 (Mode: {protagonist_mode})")
# 2. 生成路人 (如果需要)
# random 或 none 模式下补齐人数
remaining_count = 0
if protagonist_mode == "all":
remaining_count = 0
else:
remaining_count = max(0, target_total_count - spawned_protagonists_count)
if remaining_count > 0:
random_avatars = _new_make_random(
world,
count=remaining_count,
current_month_stamp=world.month_stamp,
existed_sects=existed_sects
)
final_avatars.update(random_avatars)
print(f"生成了 {len(random_avatars)} 位随机路人")
world.avatar_manager.avatars.update(final_avatars)
game_instance["world"] = world
game_instance["sim"] = sim

View File

@@ -1,4 +1,5 @@
from typing import List, Dict, Optional
import random
from src.classes.avatar import Avatar
from src.classes.world import World
from src.classes.calendar import MonthStamp
@@ -199,14 +200,23 @@ protagonist_configs = [
# 2. 执行生成与关系绑定逻辑
# ==========================================
def spawn_protagonists(world: World, current_month_stamp: MonthStamp) -> Dict[str, Avatar]:
def spawn_protagonists(
world: World,
current_month_stamp: MonthStamp,
probability: float = 1.0
) -> Dict[str, Avatar]:
"""
遍历配置生成角色,并处理特殊关系。
:param probability: 每个角色生成的概率 (0.0 - 1.0)。
"""
created_avatars = {}
# 1. 批量生成
for config in protagonist_configs:
# 概率判定
if probability < 1.0 and random.random() > probability:
continue
try:
avatar = create_avatar_from_request(
world=world,
@@ -215,10 +225,11 @@ def spawn_protagonists(world: World, current_month_stamp: MonthStamp) -> Dict[st
**config["params"]
)
created_avatars[config["key"]] = avatar
except Exception as e:
except Exception:
pass # 忽略生成错误,避免中断
# 2. 绑定关系
# 注意:需要确保双方都已生成
# 【凡人组】韩立 <-> 厉飞雨 (挚友)
if "han_li" in created_avatars and "li_fei_yu" in created_avatars:
@@ -239,4 +250,4 @@ def spawn_protagonists(world: World, current_month_stamp: MonthStamp) -> Dict[st
tong_ya.set_relation(xi_ming, Relation.PARENT)
# 返回 ID -> Avatar 字典,方便合并
return {av.id: av for av in created_avatars.values()}
return {av.id: av for av in created_avatars.values()}

View File

@@ -28,6 +28,10 @@ df:
avatar:
persona_num: 3
# all 引入所有主角不引入随机角色
# random正常随机角色但是有一定概率出主角
# none, 不引入主角(默认选项)
protagonist: "all"
social:
major_event_context_num: 10 # 大事(长期记忆)展示数量