update
This commit is contained in:
@@ -152,6 +152,7 @@
|
||||
- [ ] 天劫 & 心魔
|
||||
- [ ] 可灵活自定义的世界法则
|
||||
- [ ] 占卜 & 谶纬
|
||||
- [ ] 男生女相 & 女生男相
|
||||
|
||||
## 使用方法
|
||||
|
||||
|
||||
@@ -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
64
src/classes/effect.py
Normal 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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
@@ -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.
|
Reference in New Issue
Block a user