add wanhunfan

This commit is contained in:
bridge
2025-10-19 01:54:05 +08:00
parent a002d1bd70
commit 840046080c
7 changed files with 99 additions and 76 deletions

View File

@@ -3,18 +3,18 @@ from __future__ import annotations
from src.classes.action import TimedAction
from src.classes.event import Event
from src.classes.region import CityRegion
from src.classes.alignment import Alignment
from src.classes.technique import TechniqueAttribute
from src.classes.event import Event
import random
class DevourMortals(TimedAction):
"""
吞噬凡人:仅邪阵营可在城市区域执行,获得大量修炼经验
吞噬凡人:在城市区域执行,需持有万魂幡,吞噬魂魄可增加战力
与普通修炼相比,经验获取显著更高。
"""
COMMENT = "在城镇吞噬凡人,获得大量修行经验(邪功法)"
DOABLES_REQUIREMENTS = "仅限城市区域,且当前功法为‘邪’,且未处于瓶颈"
DOABLES_REQUIREMENTS = "仅限城市区域;持有万魂幡"
PARAMS = {}
duration_months = 2
@@ -24,18 +24,22 @@ class DevourMortals(TimedAction):
region = self.avatar.tile.region
if not isinstance(region, CityRegion):
return
if self.avatar.cultivation_progress.is_in_bottleneck():
return
self.avatar.cultivation_progress.add_exp(self.EXP_GAIN)
# 若持有万魂幡累积吞噬魂魄10~100上限10000
tr = getattr(self.avatar, "treasure", None)
if tr is not None and tr.name == "万魂幡":
gain = random.randint(10, 100)
tr.devoured_souls = min(10000, int(tr.devoured_souls) + gain)
def can_start(self) -> bool:
region = self.avatar.tile.region
if not isinstance(region, CityRegion):
return False
tech = self.avatar.technique
if tech.attribute != TechniqueAttribute.EVIL:
# 需持有万魂幡且行为被允许
tr = getattr(self.avatar, "treasure", None)
if tr is None or tr.name != "万魂幡":
return False
return not self.avatar.cultivation_progress.is_in_bottleneck()
legal = self.avatar.effects.get("legal_actions", [])
return "DevourMortals" in legal
def start(self) -> Event:
return Event(self.world.month_stamp, f"{self.avatar.name} 在城镇开始吞噬凡人")

View File

@@ -133,7 +133,7 @@ class Avatar:
def effects(self) -> dict[str, object]:
merged: dict[str, object] = defaultdict(str)
# 来自宗门
if self.sect is not None and getattr(self.sect, "effects", None):
if self.sect is not None:
merged = _merge_effects(merged, self.sect.effects)
# 来自功法
merged = _merge_effects(merged, self.technique.effects)
@@ -142,7 +142,17 @@ class Avatar:
# 来自法宝
if self.treasure is not None:
merged = _merge_effects(merged, self.treasure.effects)
return merged
# 评估动态效果表达式:值以 "eval(...)" 形式给出
evaluated: dict[str, object] = {}
for k, v in merged.items():
if isinstance(v, str):
s = v.strip()
if s.startswith("eval(") and s.endswith(")"):
expr = s[5:-1]
evaluated[k] = eval(expr, {"__builtins__": {}}, {"avatar": self})
continue
evaluated[k] = v
return evaluated
def __hash__(self) -> int:
@@ -157,6 +167,7 @@ class Avatar:
magic_stone_info = str(self.magic_stone)
if detailed:
treasure_info = self.treasure.get_detailed_info() if self.treasure is not None else ""
sect_info = self.sect.get_detailed_info() if self.sect is not None else "散修"
alignment_info = self.alignment.get_detailed_info() if self.alignment is not None else "未知"
region_info = region.get_detailed_info() if region is not None else ""
@@ -167,6 +178,7 @@ class Avatar:
items_info = "".join([f"{item.get_detailed_info()}x{quantity}" for item, quantity in self.items.items()]) if self.items else ""
appearance_info = self.appearance.get_detailed_info(self.gender)
else:
treasure_info = self.treasure.get_info() if self.treasure is not None else ""
# personas和sect一致返回detailed因为这俩太重要了
sect_info = self.sect.get_detailed_info() if self.sect is not None else "散修"
region_info = region.get_info() if region is not None else ""
@@ -178,12 +190,6 @@ class Avatar:
items_info = "".join([f"{item.get_info()}x{quantity}" for item, quantity in self.items.items()]) if self.items else ""
appearance_info = self.appearance.get_info()
# 法宝信息detailed 使用 get_detailed_info简略使用 get_info
if self.treasure is not None:
treasures_info = self.treasure.get_detailed_info() if detailed else self.treasure.get_info()
else:
treasures_info = ""
return {
"id": self.id,
"名字": self.name,
@@ -202,7 +208,7 @@ class Avatar:
"个性": personas_info,
"物品": items_info,
"外貌": appearance_info,
"法宝": treasures_info,
"法宝": treasure_info,
}
def __str__(self) -> str:
@@ -485,55 +491,70 @@ class Avatar:
"""
返回用于前端悬浮提示的多行信息。
"""
lines: list[str] = [
f"{self.name}",
f"性别: {self.gender}",
f"年龄: {self.age}",
f"外貌: {self.appearance.get_info()}",
f"阵营: {self.alignment}",
f"境界: {str(self.cultivation_progress)}",
f"HP: {self.hp}",
f"MP: {self.mp}",
f"战斗力: {int(get_base_strength(self))}",
]
lines.append(f"宗门: {self.get_sect_str()}")
from src.classes.root import format_root_cn
lines.append(f"灵根: {format_root_cn(self.root)}")
if self.technique is not None:
lines.append(f"功法: {self.technique.name}{self.technique.attribute}·{self.technique.grade.value}")
else:
lines.append("功法: 无")
if self.personas:
lines.append(f"个性: {', '.join([persona.name for persona in self.personas])}")
lines.append(f"位置: ({self.pos_x}, {self.pos_y})")
lines.append(f"灵石: {str(self.magic_stone)}")
if self.items:
lines.append("物品:")
for item, quantity in self.items.items():
lines.append(f" {item.name} x{quantity}")
else:
lines.append("")
lines.append("物品: 无")
if self.thinking:
lines.append("")
lines.append("思考:")
from src.utils.text_wrap import wrap_text
lines.extend(wrap_text(self.thinking, 28))
if getattr(self, "objective", None):
lines.append("")
lines.append("目标:")
from src.utils.text_wrap import wrap_text
lines.extend(wrap_text(self.objective, 28))
def add_kv(lines: list[str], key: str, value: object) -> None:
lines.append(f"{key}: {value}")
# 关系信息
lines.append("")
def add_section(lines: list[str], title: str, body: list[str]) -> None:
lines.append("")
lines.append(f"{title}:")
lines.extend(body)
lines: list[str] = []
# 基础信息
lines.append(f"{self.name}")
add_kv(lines, "性别", self.gender)
add_kv(lines, "年龄", self.age)
add_kv(lines, "外貌", self.appearance.get_info())
add_kv(lines, "阵营", self.alignment)
add_kv(lines, "境界", str(self.cultivation_progress))
add_kv(lines, "HP", self.hp)
add_kv(lines, "MP", self.mp)
add_kv(lines, "战斗力", int(get_base_strength(self)))
add_kv(lines, "宗门", self.get_sect_str())
from src.classes.root import format_root_cn
add_kv(lines, "灵根", format_root_cn(self.root))
if self.technique is not None:
tech_str = f"{self.technique.name}{self.technique.attribute}·{self.technique.grade.value}"
else:
tech_str = ""
add_kv(lines, "功法", tech_str)
if self.personas:
add_kv(lines, "个性", ", ".join([p.name for p in self.personas]))
add_kv(lines, "位置", f"({self.pos_x}, {self.pos_y})")
add_kv(lines, "灵石", str(self.magic_stone))
# 物品
if self.items:
items_lines = [f" {item.name} x{quantity}" for item, quantity in self.items.items()]
add_section(lines, "物品", items_lines)
else:
add_kv(lines, "物品", "")
# 思考与目标
if self.thinking:
from src.utils.text_wrap import wrap_text
add_section(lines, "思考", wrap_text(self.thinking, 28))
if getattr(self, "objective", None):
from src.utils.text_wrap import wrap_text
add_section(lines, "目标", wrap_text(self.objective, 28))
# 法宝(仅名字)
if self.treasure is not None:
add_section(lines, "法宝", [self.treasure.get_info()])
else:
add_kv(lines, "法宝", "")
# 关系
relations_list = [f"{other.name}({str(relation)})" for other, relation in getattr(self, "relations", {}).items()]
if relations_list:
lines.append("关系:")
for s in relations_list[:6]:
lines.append(f" {s}")
add_section(lines, "关系", [f" {s}" for s in relations_list[:6]])
else:
lines.append("关系: ")
add_kv(lines, "关系", "")
return lines
def get_sect_str(self) -> str:

View File

@@ -45,7 +45,6 @@ class Sect:
# 影响角色或系统的效果
effects: dict[str, object] = field(default_factory=dict)
# 功法在technique.csv中配置
# TODO法宝
# TODO宗内等级和称谓
def get_info(self) -> str:

View File

@@ -22,13 +22,16 @@ class Treasure:
desc: str
effects: dict[str, object] = field(default_factory=dict)
sect: Optional[Sect] = None
# 万魂幡专用吞噬魂魄计数0~10000
devoured_souls: int = 0
def get_info(self) -> str:
return self.name
suffix = f"(吞噬魂魄:{self.devoured_souls}" if self.name == "万魂幡" and self.devoured_souls > 0 else ""
return f"{self.name}{suffix}"
def get_detailed_info(self) -> str:
sect_name = self.sect.name if self.sect is not None else "散修可用"
return f"{self.name}宗门:{sect_name}{self.desc}"
souls = f" 吞噬魂魄:{self.devoured_souls}" if self.name == "万魂幡" and self.devoured_souls > 0 else ""
return f"{self.name}{self.desc}{souls}"
def _load_treasures() -> tuple[Dict[int, Treasure], Dict[str, Treasure], Dict[int, Treasure]]:
@@ -71,8 +74,4 @@ def _load_treasures() -> tuple[Dict[int, Treasure], Dict[str, Treasure], Dict[in
return treasures_by_id, treasures_by_name, treasures_by_sect_id
treasures_by_id, treasures_by_name, treasures_by_sect_id = _load_treasures()
for name, treasure in treasures_by_name.items():
print(name, treasure.sect.name)
treasures_by_id, treasures_by_name, treasures_by_sect_id = _load_treasures()

View File

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

View File

@@ -3,7 +3,7 @@ id,name,desc,member_act_style,alignment,sect_surnames,male_sect_given_names,fema
1,明心剑宗,通玄界东方第一宗,以无上剑道称雄于世。云纹禁制为不传心法。,清明克己,行止如一。重剑与心法并重,讲究明心见性。,,明;心;剑;霄;玄;霁;衡;孤;徽;肃,澄川;宏石;磐岳;霆岱;寂岚;久安;宸秋;烁离;沧岳;砺锋;炎洲;远歌,采微;霏岚;韶华;绮澜;珠影;远岫;若水;凝香;雪瑶;南絮;轻萝;宛竹,1,
2,百兽宗,以驯养灵兽闻名,豢养各种妖兽灵怪为战力。,你言语直接,重视力量与血性,崇尚狩猎与搏斗。,,,驼王;飞熊;虎魄;狼行;熊罡;白猿;石坚;山岚;青鬃;玄爪;金瞳;裂爪;破角;狂鬃;赤鬣;苍隼;啸风;裂岩,狐绮;白貂;青翎;雪牙;赤羽;玄狸;灵爪;月狐;银鳞;霜蹄;云貉;绒尾;锦狐;轻蹄,1,
3,水镜宗,正道十宗之一,实则严守中立。拥有仙界异宝"彻天水镜"可预知未来。,你处事冷静圆融,喜以柔克刚,擅借力与反制。,,水;镜;寒;霜;冰;清;沐;澜;渊;泉,涟光;沧浪;泽远;浩川;泊舟;涓石;溪原;涵舟;泠曜;漪岑;淞岳;涔雨,漫霖;洛漪;潋月;涵烟;沁波;翠波;漫葭;汀兰;潭歌;涓玥;澧宁;潇然,1,
4,冥王宗,行走幽冥之道,术法阴冷狠厉。,你言辞冷厉少情,敬畏因果而不惧杀伐,偏向效率与结果。,,冥;王;玄;幽;夜;白;冷;狱;魇;阴,血燎;焚魄;灰燼;殁川;绝尘;厌离;朔寒;邪风;归墟;朽骨;朔月;止戈,寒绫;霜瑶;凄歌;素鸢;祭宁;黛魂;夙梦;绫雪;凛珑;霁月;旷音;凝岚,1,
4,冥王宗,行走幽冥之道,术法阴冷狠厉。,你言辞冷厉少情,敬畏因果而不惧杀伐,偏向效率与结果。,,冥;王;玄;幽;夜;白;冷;狱;魇;阴,血燎;焚魄;灰燼;殁川;绝尘;厌离;朔寒;邪风;归墟;朽骨;朔月;止戈,寒绫;霜瑶;凄歌;素鸢;祭宁;黛魂;夙梦;绫雪;凛珑;霁月;旷音;凝岚,1000,
5,朱勾宗,邪宗大派。以炼器、机关、暗杀闻名于世,素来阴毒冷僻。,你直面欲望与代价,不惧黑暗,以攻伐见长。,,朱;绯;刃;戮;蚀;渊;钧;鸦;墨;殷,暗阑;机括;鬼匣;夜禁;幻锁;残锋;暗弦;影栅;幽钩;断线;潜匿;迷踪,玄簪;霜绡;纤罗;碎玉;影裳;轻弦;凝黛;凝烟;冷珥;素纱;凛钗;寒袖,1,
6,合欢宗,以情入道,靠双修增进修为,善驭人心,长于权变。,你辞令婉转,善于拿捏人欲与局势,以柔制刚。,,合;欢;苏;陆;柳;花;月;楚;顾;白,流烟;迟夜;长陌;归舟;暮成;远辞;行止;轻寒;沉香;野鹤;乘风,婉心;轻柔;疏影;如梦;绮念;惜香;慕雪;倾城;绯烟;晚晴;素袖;霁眉;绸缪;静妍,1000,'legal_actions': ['DualCultivation']
7,镇魂宗,铁血风格,擅安魂、封邪、渡厄,兼有刚烈镇压之术。,你肃穆沉稳,重安魂镇邪,少言而果决。,,厉;卢;镇;魂;钟;青;凌;白;楚;顾,安魄;靖川;霁阳;季衡;砺甲;烁锋;昊戈;祁光;漠石;启封;殷策;定魄,清宁;素铃;靖霜;澄心;霁雪;安祈;净月;宁枝;祷绫;明槐;采霁;定寒,1,
Can't render this file because it contains an unexpected character in line 5 and column 73.

View File

@@ -5,7 +5,7 @@ id,name,sect_id,desc,effects
3,千里镜,3,澄澈如镜,观千里之外,洞察先机.,"extra_observation_radius": 2
4,镇魂钟,7,钟鸣摄魄,定魂镇邪,护心安魂.,"extra_battle_strength_points": 3; "extra_observation_radius": 1
5,聚灵阵盘,5,刻阵成盘,聚纳灵机,修行事半功倍.,"extra_cultivate_exp": 50
6,万魂幡,4,幡起万魂啾啾,阴风过境。(效果留空,后续配置),
6,万魂幡,4,幡起万魂啾啾,阴风过境.,"legal_actions": ["DevourMortals"]; "extra_battle_strength_points": eval(avatar.treasure.devoured_souls // 100 * 0.1)
7,万欲同心结,6,情意同心,双修之道相互映照,修为更精进.,"extra_dual_cultivation_exp": 100
8,影遁披风,8,融身影界,来去无踪,伏击出其不意.,"extra_move_step": 1; "extra_observation_radius": 1
Can't render this file because it contains an unexpected character in line 2 and column 99.