This commit is contained in:
bridge
2025-10-16 00:43:31 +08:00
parent 4295145934
commit 9d9d9737e5
9 changed files with 117 additions and 21 deletions

View File

@@ -152,6 +152,7 @@
- [ ] 天劫 & 心魔
- [ ] 可灵活自定义的世界法则
- [ ] 占卜 & 谶纬
- [ ] 男生女相 & 女生男相
## 使用方法

View File

@@ -2,6 +2,7 @@ import random
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, List
from collections import defaultdict
import json
from src.classes.calendar import MonthStamp
@@ -18,7 +19,7 @@ from src.classes.age import Age
from src.classes.event import NULL_EVENT, Event
from src.classes.typings import ACTION_NAME, ACTION_PARAMS, ACTION_NAME_PARAMS_PAIRS, ACTION_NAME_PARAMS_PAIR
from src.classes.action_runtime import ActionPlan, ActionInstance
from src.classes.effect import _merge_effects
from src.classes.persona import Persona, personas_by_id, get_random_compatible_personas
from src.classes.item import Item
from src.classes.magic_stone import MagicStone
@@ -87,6 +88,7 @@ class Avatar:
appearance: Appearance = field(default_factory=get_random_appearance)
# 当月/当步新设动作标记:在 commit_next_plan 设为 True首次 tick_action 后清为 False
_new_action_set_this_step: bool = False
# 不缓存 effects实时从宗门与功法合并
def __post_init__(self):
"""
@@ -120,6 +122,18 @@ class Avatar:
from src.classes.alignment import Alignment as _Alignment
self.alignment = random.choice(list(_Alignment))
# effects 改为实时属性,不在此初始化
@property
def effects(self) -> dict[str, object]:
merged: dict[str, object] = defaultdict(str)
if self.sect is not None and getattr(self.sect, "effects", None):
merged = _merge_effects(merged, self.sect.effects)
if self.technique is not None and getattr(self.technique, "effects", None):
merged = _merge_effects(merged, self.technique.effects)
return merged
def __hash__(self) -> int:
return hash(self.id)

64
src/classes/effect.py Normal file
View File

@@ -0,0 +1,64 @@
from __future__ import annotations
import json
import ast
from typing import Any
def load_effect_from_str(value: object) -> dict[str, Any]:
"""
解析 effects 字符串为 dict
- 支持 JSON 格式(双引号)
- 支持 Python 字面量(单引号,如 {'k': ['v']})
- value 为 None/空字符串/'nan' 时返回 {}
- 解析非 dict 则返回 {}
"""
if value is None:
return {}
if isinstance(value, dict):
return value
s = str(value).strip()
if not s or s == "nan":
return {}
try:
obj = json.loads(s)
return obj if isinstance(obj, dict) else {}
except Exception:
try:
obj = ast.literal_eval(s)
return obj if isinstance(obj, dict) else {}
except Exception:
return {}
def _merge_effects(base: dict[str, object], addition: dict[str, object]) -> dict[str, object]:
"""
合并两个 effects 字典:
- list 型(如 legal_actions做去重并集
- 数值型:相加
- 其他:后者覆盖前者
返回新字典,不修改原对象。
"""
if not base and not addition:
return {}
merged: dict[str, object] = dict(base) if base else {}
for key, val in (addition or {}).items():
if key in merged:
old = merged[key]
if isinstance(old, list) and isinstance(val, list):
# 去重并集,保持相对顺序
seen: set[object] = set()
result: list[object] = []
for x in old + val:
if x in seen:
continue
seen.add(x)
result.append(x)
merged[key] = result
elif isinstance(old, (int, float)) and isinstance(val, (int, float)):
merged[key] = old + val
else:
merged[key] = val
else:
merged[key] = val
return merged

View File

@@ -38,9 +38,10 @@ class DualCultivation(MutualAction):
def can_start(self, target_avatar: "Avatar|str|None" = None) -> bool:
if target_avatar is None:
return False
# 必须为合欢宗
sect = self.avatar.sect
if sect is None or sect.name != "合欢宗":
# 基于 effects 判断是否允许
effects = self.avatar.effects
legal_actions = effects["legal_actions"]
if not isinstance(legal_actions, list) or "DualCultivation" not in legal_actions:
return False
target = self._get_target_avatar(target_avatar)
if target is None:

View File

@@ -1,8 +1,10 @@
from dataclasses import dataclass
from dataclasses import dataclass, field
from pathlib import Path
import json
from src.classes.alignment import Alignment
from src.utils.df import game_configs
from src.classes.effect import load_effect_from_str
from src.utils.config import CONFIG
@@ -40,6 +42,8 @@ class Sect:
technique_names: list[str]
# 随机选择宗门时使用的权重默认1
weight: float = 1.0
# 影响角色或系统的效果
effects: dict[str, object] = field(default_factory=dict)
# 功法在technique.csv中配置
# TODO法宝
# TODO宗内等级和称谓
@@ -86,6 +90,9 @@ def _load_sects() -> tuple[dict[int, Sect], dict[str, Sect]]:
weight_val = row.get("weight", 1)
weight = float(str(weight_val)) if str(weight_val) != "nan" else 1.0
# 读取 effects兼容 JSON/单引号字面量/空)
effects = load_effect_from_str(row.get("effects", ""))
sect = Sect(
id=int(row["id"]),
name=str(row["name"]),
@@ -103,6 +110,7 @@ def _load_sects() -> tuple[dict[int, Sect], dict[str, Sect]]:
),
technique_names=technique_names,
weight=weight,
effects=effects,
)
sects_by_id[sect.id] = sect
sects_by_name[sect.name] = sect

View File

@@ -1,8 +1,10 @@
from __future__ import annotations
from dataclasses import dataclass
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, Dict, List
import json
from src.classes.effect import load_effect_from_str
from src.utils.df import game_configs
from src.classes.alignment import Alignment
@@ -51,6 +53,8 @@ class Technique:
condition: str
# 归属宗门名称None/空表示无宗门要求(散修可修)
sect: Optional[str] = None
# 影响角色或系统的效果
effects: dict[str, object] = field(default_factory=dict)
def is_allowed_for(self, avatar) -> bool:
if not self.condition:
@@ -96,6 +100,9 @@ def loads() -> tuple[dict[int, Technique], dict[str, Technique]]:
weight = float(str(weight_val)) if str(weight_val) != "nan" else 1.0
sect_val = row.get("sect", "")
sect = None if str(sect_val) == "nan" or str(sect_val).strip() == "" else str(sect_val).strip()
# 读取 effects兼容 JSON/单引号字面量/空)
effects = load_effect_from_str(row.get("effects", ""))
t = Technique(
id=int(row["id"]),
name=name,
@@ -105,6 +112,7 @@ def loads() -> tuple[dict[int, Technique], dict[str, Technique]]:
weight=weight,
condition=condition,
sect=sect,
effects=effects,
)
techniques_by_id[t.id] = t
techniques_by_name[t.name] = t

View File

@@ -15,8 +15,8 @@ ai:
max_decide_num: 4
game:
init_npc_num: 2
sect_num: 3 # init_npc_num大于sect_num时会随机选择sect_num个宗门
init_npc_num: 9
sect_num: 2 # init_npc_num大于sect_num时会随机选择sect_num个宗门
npc_birth_rate_per_month: 0.001
df:

View File

@@ -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,你绝不轻易放下仇怨,为了复仇愿意付出代价与时间。你必须立刻进行复仇行动。,1000,
12,复仇,11;14,你绝不轻易放下仇怨,为了复仇愿意付出代价与时间。你必须立刻进行复仇行动。,1,
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,你对待和他人结为道侣或者双修比较随意,1,
26,开放,27,你对待和他人结为道侣或者双修比较随意,1000,
27,腼腆,26,你对待和他人结为道侣或者双修比较谨慎,1,
28,舔狗,13;14;22;27,你对异性中外貌出众者格外友善,倾向主动接近、帮助与合作。,1,
29,嫉妒,11;23,你对在修为、外貌或财富等方面远超于你的人容易产生敌意,更倾向对其冷淡、挑衅或打压。,1,
Can't render this file because it contains an unexpected character in line 26 and column 121.

View File

@@ -1,11 +1,11 @@
id,name,desc,member_act_style,alignment,sect_surnames,male_sect_given_names,female_sect_given_names,weight
,,宗门名称与描述,宗门成员行事风格,阵营(正/中/邪),宗门常用姓氏(分号分隔),男性常用名(分号分隔),女性常用名(分号分隔),权重(默认1)
1,明心剑宗,通玄界东方第一宗,以无上剑道称雄于世。云纹禁制为不传心法。,清明克己,行止如一。重剑与心法并重,讲究明心见性。,,明;心;剑;霄;玄;霁;衡;孤;徽;肃,澄川;宏石;磐岳;霆岱;寂岚;久安;宸秋;烁离;沧岳;砺锋;炎洲;远歌,采微;霏岚;韶华;绮澜;珠影;远岫;若水;凝香;雪瑶;南絮;轻萝;宛竹,1
2,百兽宗,以驯养灵兽闻名,豢养各种妖兽灵怪为战力。,你言语直接,重视力量与血性,崇尚狩猎与搏斗。,,,驼王;飞熊;虎魄;狼行;熊罡;白猿;石坚;山岚;青鬃;玄爪;金瞳;裂爪;破角;狂鬃;赤鬣;苍隼;啸风;裂岩,狐绮;白貂;青翎;雪牙;赤羽;玄狸;灵爪;月狐;银鳞;霜蹄;云貉;绒尾;锦狐;轻蹄,1
3,水镜宗,正道十宗之一,实则严守中立。拥有仙界异宝"彻天水镜"可预知未来。,你处事冷静圆融,喜以柔克刚,擅借力与反制。,,水;镜;寒;霜;冰;清;沐;澜;渊;泉,涟光;沧浪;泽远;浩川;泊舟;涓石;溪原;涵舟;泠曜;漪岑;淞岳;涔雨,漫霖;洛漪;潋月;涵烟;沁波;翠波;漫葭;汀兰;潭歌;涓玥;澧宁;潇然,1
4,冥王宗,行走幽冥之道,术法阴冷狠厉。,你言辞冷厉少情,敬畏因果而不惧杀伐,偏向效率与结果。,,冥;王;玄;幽;夜;白;冷;狱;魇;阴,血燎;焚魄;灰燼;殁川;绝尘;厌离;朔寒;邪风;归墟;朽骨;朔月;止戈,寒绫;霜瑶;凄歌;素鸢;祭宁;黛魂;夙梦;绫雪;凛珑;霁月;旷音;凝岚,1
5,朱勾宗,邪宗大派。以炼器、机关、暗杀闻名于世,素来阴毒冷僻。,你直面欲望与代价,不惧黑暗,以攻伐见长。,,朱;绯;刃;戮;蚀;渊;钧;鸦;墨;殷,暗阑;机括;鬼匣;夜禁;幻锁;残锋;暗弦;影栅;幽钩;断线;潜匿;迷踪,玄簪;霜绡;纤罗;碎玉;影裳;轻弦;凝黛;凝烟;冷珥;素纱;凛钗;寒袖,1
6,合欢宗,以情入道,靠双修增进修为,善驭人心,长于权变。,你辞令婉转,善于拿捏人欲与局势,以柔制刚。,,合;欢;苏;陆;柳;花;月;楚;顾;白,流烟;迟夜;长陌;归舟;暮成;远辞;行止;轻寒;沉香;野鹤;乘风,婉心;轻柔;疏影;如梦;绮念;惜香;慕雪;倾城;绯烟;晚晴;素袖;霁眉;绸缪;静妍,1000
7,镇魂宗,铁血风格,擅安魂、封邪、渡厄,兼有刚烈镇压之术。,你肃穆沉稳,重安魂镇邪,少言而果决。,,厉;卢;镇;魂;钟;青;凌;白;楚;顾,安魄;靖川;霁阳;季衡;砺甲;烁锋;昊戈;祁光;漠石;启封;殷策;定魄,清宁;素铃;靖霜;澄心;霁雪;安祈;净月;宁枝;祷绫;明槐;采霁;定寒,1
8,幽魂噬影宗,镇宗典籍《幽冥录》。幽明气为根基。,你行事隐秘果断,重结果轻虚名,擅潜行与出其不意。,,冥;阎;鬼;幽;归;应;阴;碧;夜;魅,噬影;无藏;绝响;断痕;影渊;暗行;潜踪;魄隐;迷雾;空蝉;断念;裂隙,影绫;暗萝;霜绡;素鹭;玄绮;凝灯;绫岚;凛铃;朔华;漠音;宵岑;泠歌,1
9,千帆城,炼器大宗,巧匠云集。著名法宝有灵灭丝、定魂蓝星、天罗网、万里极光壁、飞翼等。商旅云集,自成体系。,你务实精明,重交易与信誉,崇尚规则与秩序。,,商;楚;顾;白;苏;林;叶;秦;赵;魏,持衡;清评;问价;立契;通衡;问道;理市;衡准;守约;筑匠;铸衡;估算,素蓝;明衡;巧心;青帆;绫舟;观星;衡绫;星槎;织霓;采绫;芸巧;霁行;砚秋;镶玑;绘蓝;银梭;珩心,1
id,name,desc,member_act_style,alignment,sect_surnames,male_sect_given_names,female_sect_given_names,weight,effects
,,宗门名称与描述,宗门成员行事风格,阵营(正/中/邪),宗门常用姓氏(分号分隔),男性常用名(分号分隔),女性常用名(分号分隔),权重(默认1),effects(JSON)
1,明心剑宗,通玄界东方第一宗,以无上剑道称雄于世。云纹禁制为不传心法。,清明克己,行止如一。重剑与心法并重,讲究明心见性。,,明;心;剑;霄;玄;霁;衡;孤;徽;肃,澄川;宏石;磐岳;霆岱;寂岚;久安;宸秋;烁离;沧岳;砺锋;炎洲;远歌,采微;霏岚;韶华;绮澜;珠影;远岫;若水;凝香;雪瑶;南絮;轻萝;宛竹,1,
2,百兽宗,以驯养灵兽闻名,豢养各种妖兽灵怪为战力。,你言语直接,重视力量与血性,崇尚狩猎与搏斗。,,,驼王;飞熊;虎魄;狼行;熊罡;白猿;石坚;山岚;青鬃;玄爪;金瞳;裂爪;破角;狂鬃;赤鬣;苍隼;啸风;裂岩,狐绮;白貂;青翎;雪牙;赤羽;玄狸;灵爪;月狐;银鳞;霜蹄;云貉;绒尾;锦狐;轻蹄,1,
3,水镜宗,正道十宗之一,实则严守中立。拥有仙界异宝"彻天水镜"可预知未来。,你处事冷静圆融,喜以柔克刚,擅借力与反制。,,水;镜;寒;霜;冰;清;沐;澜;渊;泉,涟光;沧浪;泽远;浩川;泊舟;涓石;溪原;涵舟;泠曜;漪岑;淞岳;涔雨,漫霖;洛漪;潋月;涵烟;沁波;翠波;漫葭;汀兰;潭歌;涓玥;澧宁;潇然,1,
4,冥王宗,行走幽冥之道,术法阴冷狠厉。,你言辞冷厉少情,敬畏因果而不惧杀伐,偏向效率与结果。,,冥;王;玄;幽;夜;白;冷;狱;魇;阴,血燎;焚魄;灰燼;殁川;绝尘;厌离;朔寒;邪风;归墟;朽骨;朔月;止戈,寒绫;霜瑶;凄歌;素鸢;祭宁;黛魂;夙梦;绫雪;凛珑;霁月;旷音;凝岚,1,
5,朱勾宗,邪宗大派。以炼器、机关、暗杀闻名于世,素来阴毒冷僻。,你直面欲望与代价,不惧黑暗,以攻伐见长。,,朱;绯;刃;戮;蚀;渊;钧;鸦;墨;殷,暗阑;机括;鬼匣;夜禁;幻锁;残锋;暗弦;影栅;幽钩;断线;潜匿;迷踪,玄簪;霜绡;纤罗;碎玉;影裳;轻弦;凝黛;凝烟;冷珥;素纱;凛钗;寒袖,1,
6,合欢宗,以情入道,靠双修增进修为,善驭人心,长于权变。,你辞令婉转,善于拿捏人欲与局势,以柔制刚。,,合;欢;苏;陆;柳;花;月;楚;顾;白,流烟;迟夜;长陌;归舟;暮成;远辞;行止;轻寒;沉香;野鹤;乘风,婉心;轻柔;疏影;如梦;绮念;惜香;慕雪;倾城;绯烟;晚晴;素袖;霁眉;绸缪;静妍,1000,{'legal_actions': ['DualCultivation']}
7,镇魂宗,铁血风格,擅安魂、封邪、渡厄,兼有刚烈镇压之术。,你肃穆沉稳,重安魂镇邪,少言而果决。,,厉;卢;镇;魂;钟;青;凌;白;楚;顾,安魄;靖川;霁阳;季衡;砺甲;烁锋;昊戈;祁光;漠石;启封;殷策;定魄,清宁;素铃;靖霜;澄心;霁雪;安祈;净月;宁枝;祷绫;明槐;采霁;定寒,1,
8,幽魂噬影宗,镇宗典籍《幽冥录》。幽明气为根基。,你行事隐秘果断,重结果轻虚名,擅潜行与出其不意。,,冥;阎;鬼;幽;归;应;阴;碧;夜;魅,噬影;无藏;绝响;断痕;影渊;暗行;潜踪;魄隐;迷雾;空蝉;断念;裂隙,影绫;暗萝;霜绡;素鹭;玄绮;凝灯;绫岚;凛铃;朔华;漠音;宵岑;泠歌,1,
9,千帆城,炼器大宗,巧匠云集。著名法宝有灵灭丝、定魂蓝星、天罗网、万里极光壁、飞翼等。商旅云集,自成体系。,你务实精明,重交易与信誉,崇尚规则与秩序。,,商;楚;顾;白;苏;林;叶;秦;赵;魏,持衡;清评;问价;立契;通衡;问道;理市;衡准;守约;筑匠;铸衡;估算,素蓝;明衡;巧心;青帆;绫舟;观星;衡绫;星槎;织霓;采绫;芸巧;霁行;砚秋;镶玑;绘蓝;银梭;珩心,1,
Can't render this file because it contains an unexpected character in line 5 and column 73.