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)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user