add alignment
This commit is contained in:
@@ -6,6 +6,7 @@ import random
|
||||
|
||||
from src.classes.root import Root, get_essence_types_for_root, extra_breakthrough_success_rate
|
||||
from src.classes.region import Region, CultivateRegion, NormalRegion, CityRegion
|
||||
from src.classes.alignment import Alignment
|
||||
from src.classes.event import Event, NULL_EVENT
|
||||
from src.classes.item import Item, items_by_name
|
||||
from src.classes.prices import prices
|
||||
@@ -689,3 +690,77 @@ class Battle(DefineAction, ActualActionMixin):
|
||||
winner, loser = res
|
||||
return [Event(self.world.month_stamp, f"{winner} 战胜了 {loser}")]
|
||||
return []
|
||||
|
||||
|
||||
@long_action(step_month=3)
|
||||
class PlunderMortals(DefineAction, ActualActionMixin):
|
||||
"""
|
||||
在城镇对凡人进行搜刮,获取少量灵石。
|
||||
仅邪阵营可执行。
|
||||
"""
|
||||
COMMENT = "在城镇搜刮凡人,获取少量灵石"
|
||||
DOABLES_REQUIREMENTS = "仅限城市区域,且角色阵营为‘邪’"
|
||||
PARAMS = {}
|
||||
GAIN = 20
|
||||
|
||||
def _execute(self) -> None:
|
||||
region = self.avatar.tile.region
|
||||
if not isinstance(region, CityRegion):
|
||||
return
|
||||
gain = self.GAIN
|
||||
self.avatar.magic_stone = self.avatar.magic_stone + gain
|
||||
|
||||
def can_start(self) -> bool:
|
||||
region = self.avatar.tile.region
|
||||
if not isinstance(region, CityRegion):
|
||||
return False
|
||||
return self.avatar.alignment == Alignment.EVIL
|
||||
|
||||
def start(self) -> Event:
|
||||
return Event(self.world.month_stamp, f"{self.avatar.name} 在城镇开始搜刮凡人")
|
||||
|
||||
def step(self) -> tuple[StepStatus, list[Event]]:
|
||||
self.execute()
|
||||
return (StepStatus.COMPLETED if getattr(self, "is_finished")() else StepStatus.RUNNING), []
|
||||
|
||||
def finish(self) -> list[Event]:
|
||||
return []
|
||||
|
||||
|
||||
@long_action(step_month=3)
|
||||
class HelpMortals(DefineAction, ActualActionMixin):
|
||||
"""
|
||||
在城镇帮助凡人,消耗少量灵石。
|
||||
仅正阵营可执行。
|
||||
"""
|
||||
COMMENT = "在城镇帮助凡人,消耗少量灵石"
|
||||
DOABLES_REQUIREMENTS = "仅限城市区域,且角色阵营为‘正’,并且灵石足够"
|
||||
PARAMS = {}
|
||||
COST = 10
|
||||
|
||||
def _execute(self) -> None:
|
||||
region = self.avatar.tile.region
|
||||
if not isinstance(region, CityRegion):
|
||||
return
|
||||
cost = self.COST
|
||||
if getattr(self.avatar.magic_stone, "value", 0) >= cost:
|
||||
self.avatar.magic_stone = self.avatar.magic_stone - cost
|
||||
|
||||
def can_start(self) -> bool:
|
||||
region = self.avatar.tile.region
|
||||
if not isinstance(region, CityRegion):
|
||||
return False
|
||||
if self.avatar.alignment != Alignment.RIGHTEOUS:
|
||||
return False
|
||||
cost = self.COST
|
||||
return getattr(self.avatar.magic_stone, "value", 0) >= cost
|
||||
|
||||
def start(self) -> Event:
|
||||
return Event(self.world.month_stamp, f"{self.avatar.name} 在城镇开始帮助凡人")
|
||||
|
||||
def step(self) -> tuple[StepStatus, list[Event]]:
|
||||
self.execute()
|
||||
return (StepStatus.COMPLETED if getattr(self, "is_finished")() else StepStatus.RUNNING), []
|
||||
|
||||
def finish(self) -> list[Event]:
|
||||
return []
|
||||
|
||||
@@ -13,6 +13,8 @@ from src.classes.action import (
|
||||
Harvest,
|
||||
Sold,
|
||||
Battle,
|
||||
PlunderMortals,
|
||||
HelpMortals,
|
||||
)
|
||||
from src.classes.mutual_action import (
|
||||
DriveAway,
|
||||
@@ -33,6 +35,8 @@ ALL_ACTION_CLASSES = [
|
||||
Hunt,
|
||||
Harvest,
|
||||
Sold,
|
||||
PlunderMortals,
|
||||
HelpMortals,
|
||||
# 互动相关动作(实际执行的反馈动作也纳入)
|
||||
DriveAway,
|
||||
Attack,
|
||||
@@ -49,6 +53,8 @@ ALL_ACTUAL_ACTION_CLASSES = [
|
||||
Hunt,
|
||||
Harvest,
|
||||
Sold,
|
||||
PlunderMortals,
|
||||
HelpMortals,
|
||||
DriveAway,
|
||||
Attack,
|
||||
]
|
||||
|
||||
21
src/classes/alignment.py
Normal file
21
src/classes/alignment.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Alignment(Enum):
|
||||
"""
|
||||
阵营:正/邪。
|
||||
值使用英文,便于与代码/保存兼容;__str__ 返回中文。
|
||||
"""
|
||||
RIGHTEOUS = "righteous" # 正
|
||||
EVIL = "evil" # 邪
|
||||
|
||||
def __str__(self) -> str:
|
||||
return alignment_strs.get(self, self.value)
|
||||
|
||||
|
||||
alignment_strs = {
|
||||
Alignment.RIGHTEOUS: "正",
|
||||
Alignment.EVIL: "邪",
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from src.utils.id_generator import get_avatar_id
|
||||
from src.utils.config import CONFIG
|
||||
from src.classes.relation import Relation
|
||||
from src.run.log import get_logger
|
||||
from src.classes.alignment import Alignment
|
||||
|
||||
persona_num = CONFIG.avatar.persona_num
|
||||
|
||||
@@ -73,6 +74,7 @@ class Avatar:
|
||||
hp: HP = field(default_factory=lambda: HP(0, 0)) # 将在__post_init__中初始化
|
||||
mp: MP = field(default_factory=lambda: MP(0, 0)) # 将在__post_init__中初始化
|
||||
relations: dict["Avatar", Relation] = field(default_factory=dict)
|
||||
alignment: Alignment = field(default_factory=lambda: random.choice(list(Alignment)))
|
||||
|
||||
def __post_init__(self):
|
||||
"""
|
||||
@@ -101,7 +103,7 @@ class Avatar:
|
||||
尽量多打一些,因为会用来给LLM进行决策
|
||||
"""
|
||||
personas_str = ", ".join([persona.name for persona in self.personas])
|
||||
return f"Avatar(id={self.id}, 性别={self.gender}, 年龄={self.age}, name={self.name}, 区域={self.tile.region.name}, 灵根={str(self.root)}, 境界={self.cultivation_progress}, HP={self.hp}, MP={self.mp}, 个性={personas_str})"
|
||||
return f"Avatar(id={self.id}, 性别={self.gender}, 年龄={self.age}, name={self.name}, 阵营={self.alignment}, 区域={self.tile.region.name}, 灵根={str(self.root)}, 境界={self.cultivation_progress}, HP={self.hp}, MP={self.mp}, 个性={personas_str})"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.get_info()
|
||||
@@ -437,11 +439,11 @@ class Avatar:
|
||||
|
||||
def get_other_avatar_info(self, other_avatar: "Avatar") -> str:
|
||||
"""
|
||||
仅显示三个字段:名字、境界、关系。
|
||||
仅显示4个字段:名字、境界、关系、阵营。
|
||||
"""
|
||||
relation = self.get_relation(other_avatar)
|
||||
relation_str = str(relation)
|
||||
return f"{other_avatar.name},境界:{other_avatar.cultivation_progress.get_simple_info()},关系:{relation_str}"
|
||||
return f"{other_avatar.name},境界:{other_avatar.cultivation_progress.get_simple_info()},关系:{relation_str},阵营:{other_avatar.alignment}"
|
||||
|
||||
@property
|
||||
def move_step_length(self) -> int:
|
||||
|
||||
@@ -25,4 +25,31 @@ class AvatarManager:
|
||||
same_region.append(other)
|
||||
return same_region
|
||||
|
||||
def remove_avatar(self, avatar_id: str) -> None:
|
||||
"""
|
||||
从管理器中删除一个 avatar,并清理所有与其相关的双向关系。
|
||||
"""
|
||||
avatar = self.avatars.get(avatar_id)
|
||||
if avatar is None:
|
||||
return
|
||||
# 先清理与其直接记录的关系(会保持对称)
|
||||
related = list(getattr(avatar, "relations", {}).keys())
|
||||
for other in related:
|
||||
avatar.clear_relation(other)
|
||||
# 再次扫一遍所有 avatar,确保不存在残留引用
|
||||
for other in list(self.avatars.values()):
|
||||
if other is avatar:
|
||||
continue
|
||||
if getattr(other, "relations", None) is not None and avatar in other.relations:
|
||||
other.clear_relation(avatar)
|
||||
# 最后移除自身
|
||||
self.avatars.pop(avatar_id, None)
|
||||
|
||||
def remove_avatars(self, avatar_ids: List[str]) -> None:
|
||||
"""
|
||||
批量删除 avatars,并清理所有关系。
|
||||
"""
|
||||
for aid in list(avatar_ids):
|
||||
self.remove_avatar(aid)
|
||||
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ def draw_tooltip_for_avatar(pygame_mod, screen, colors, font, avatar: Avatar):
|
||||
f"{avatar.name}",
|
||||
f"性别: {avatar.gender}",
|
||||
f"年龄: {avatar.age}",
|
||||
f"阵营: {avatar.alignment}",
|
||||
f"境界: {str(avatar.cultivation_progress)}",
|
||||
f"HP: {avatar.hp}",
|
||||
f"MP: {avatar.mp}",
|
||||
|
||||
@@ -24,6 +24,7 @@ from src.utils.id_generator import get_avatar_id
|
||||
from src.utils.config import CONFIG
|
||||
from src.run.log import get_logger
|
||||
from src.classes.relation import Relation
|
||||
from src.classes.alignment import Alignment
|
||||
|
||||
|
||||
def clamp(value: int, lo: int, hi: int) -> int:
|
||||
@@ -85,6 +86,8 @@ def make_avatars(world: World, count: int = 12, current_month_stamp: MonthStamp
|
||||
root=random.choice(list(Root)), # 随机选择灵根
|
||||
)
|
||||
avatar.tile = world.map.get_tile(x, y)
|
||||
# 随机分配阵营(正/邪)
|
||||
avatar.alignment = random.choice(list(Alignment))
|
||||
avatars[avatar.id] = avatar
|
||||
# —— 为演示添加少量示例关系 ——
|
||||
avatar_list = list(avatars.values())
|
||||
|
||||
@@ -56,7 +56,7 @@ class Simulator:
|
||||
if new_events:
|
||||
events.extend(new_events)
|
||||
|
||||
# 结算战斗等导致的死亡(HP<=0)与寿命逻辑
|
||||
# 结算战斗等导致的死亡逻辑
|
||||
for avatar_id, avatar in list(self.world.avatar_manager.avatars.items()):
|
||||
if avatar.hp <= 0:
|
||||
death_avatar_ids.append(avatar_id)
|
||||
@@ -66,11 +66,15 @@ class Simulator:
|
||||
death_avatar_ids.append(avatar_id)
|
||||
event = Event(self.world.month_stamp, f"{avatar.name} 老死了,时年{avatar.age.get_age()}岁")
|
||||
events.append(event)
|
||||
# 删除死亡的角色(由 AvatarManager 清理关系并移除)
|
||||
if death_avatar_ids:
|
||||
self.world.avatar_manager.remove_avatars(death_avatar_ids)
|
||||
|
||||
# 寿命逻辑
|
||||
for avatar_id, avatar in self.world.avatar_manager.avatars.items():
|
||||
avatar.update_age(self.world.month_stamp)
|
||||
|
||||
# 删除死亡的角色
|
||||
for avatar_id in death_avatar_ids:
|
||||
self.world.avatar_manager.avatars.pop(avatar_id)
|
||||
|
||||
|
||||
# 新角色
|
||||
if random.random() < self.birth_rate:
|
||||
|
||||
@@ -20,4 +20,4 @@ df:
|
||||
ids_separator: ";"
|
||||
|
||||
avatar:
|
||||
persona_num: 1
|
||||
persona_num: 3
|
||||
@@ -1,3 +1,22 @@
|
||||
id,name,exclusion_ids,prompt
|
||||
,,和本persona互斥的persona的id,输入给LLM的prompt
|
||||
12,复仇,11;14,你是一个复仇心强的人,你绝不轻易放下仇怨,为了复仇愿意付出代价与时间。你要立刻复仇。
|
||||
1,理性,2;5,你是一个理性的人,你总是会用逻辑来思考问题,做事会谋定而后动。
|
||||
2,无常,1;9;20,你是一个无常的人,目标飘忽不定,不会长期坚持一个目标。
|
||||
3,怠惰,4;20,你是一个怠惰的人,你总是会拖延,不想努力,更热衷于享受人生。
|
||||
4,冒险,3;10,你是一个冒险的人,你总是会冒险,喜欢刺激,总想放手一搏。
|
||||
5,随性,1;20,你是一个随性的人,你总是会随机应变,性子到哪里了就是哪里,没有一定之规。
|
||||
6,贪财,,你是一个贪财的人,你对灵石和财富有着强烈的渴望。
|
||||
7,采药,,你是一个热爱采集的人,喜欢在山林中寻找各种奇花异草和灵药,对植物有着敏锐的直觉和深厚的兴趣。你认为大自然的恩赐需要用心去发现和珍惜。
|
||||
8,猎者,,你是一个热爱狩猎的人,享受在野外追踪猎物的刺激感,对各种动物的习性了如指掌。你相信通过狩猎能够磨练自己的意志和技能,获得更强大的力量。
|
||||
9,沉思,2,你是一个沉思的人,你总是会深思熟虑,思考问题比较有哲理。
|
||||
10,惜命,4;20,你是一个惜命的人,你总是会珍惜自己的生命,不会轻易冒险。
|
||||
11,友爱,13;14;15;12;20,你是一个友爱的人,你重视同伴与和谐,乐于助人,倾向通过协作与沟通化解矛盾。
|
||||
12,复仇,11;14,你是一个复仇心强的人,你绝不轻易放下仇怨,为了复仇愿意付出代价与时间。
|
||||
13,孤僻,11,你是一个孤僻的人,你喜欢独处,避免与人深交,更信赖自己的判断与行动。
|
||||
14,淡漠,11;12;15;20,你是一个淡漠的人,你情感克制,对外界冷静疏离,不轻易被他人或事件影响。
|
||||
15,好斗,11;14;10;17,你是一个好斗的人,你直面冲突,偏好以力量与对抗解决问题,越挫越勇。
|
||||
16,鲁莽,1;9;10,你是一个鲁莽的人,你行事冲动、少考虑后果,常凭直觉立刻行动。
|
||||
17,胆小,4;15;12;20,你是一个胆小的人,你谨小慎微,容易畏惧风险,倾向回避正面冲突。
|
||||
18,霸道,11;17,你是一个霸道的人,你行事强势,不讲道理,习惯以自己的利益为先,倾向多吃多占、压人一步,对他人的反对不以为意。
|
||||
19,修行痴迷,2;3;5,你是一个对修行极度痴迷的人,你将绝大多数时间用于修炼,厌恶与修行无关的社交与享乐。
|
||||
20,极端,11;14;2;5;3;10;17,你是一个极端的人,你仇视对立阵营,如果你是正义阵营,那么你极度正义;如果你是邪恶阵营,那么你极度邪恶。
|
||||
|
||||
|
Reference in New Issue
Block a user