update distance
This commit is contained in:
@@ -4,7 +4,7 @@ from src.classes.action import InstantAction, Move
|
||||
from src.classes.event import Event
|
||||
from src.classes.action.move_helper import clamp_manhattan_with_diagonal_priority
|
||||
from src.classes.region import Region, resolve_region
|
||||
from src.classes.region import resolve_region
|
||||
from src.utils.distance import euclidean_distance
|
||||
|
||||
|
||||
class MoveAwayFromRegion(InstantAction):
|
||||
@@ -19,7 +19,7 @@ class MoveAwayFromRegion(InstantAction):
|
||||
y = self.avatar.pos_y
|
||||
# 找到目标区域内距离当前坐标最近的格点
|
||||
if getattr(r, "cors", None):
|
||||
nearest = min(r.cors, key=lambda p: (p[0] - x) * (p[0] - x) + (p[1] - y) * (p[1] - y))
|
||||
nearest = min(r.cors, key=lambda p: euclidean_distance((x, y), p))
|
||||
away_dx = x - nearest[0]
|
||||
away_dy = y - nearest[1]
|
||||
else:
|
||||
|
||||
1
src/classes/action/move_to_direction.py
Normal file
1
src/classes/action/move_to_direction.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -70,8 +70,8 @@ class LLMAI(AI):
|
||||
"""
|
||||
general_action_infos = ACTION_INFOS_STR
|
||||
async def decide_one(avatar: Avatar):
|
||||
# 获取基于该角色已知区域的世界信息
|
||||
world_info = world.get_info(known_region_ids=avatar.known_regions)
|
||||
# 获取基于该角色已知区域的世界信息(包含距离计算)
|
||||
world_info = world.get_info(avatar=avatar)
|
||||
|
||||
# 在提示中包含处于角色观测范围内的其他角色
|
||||
observed = world.get_observable_avatars(avatar)
|
||||
|
||||
@@ -78,8 +78,8 @@ async def generate_long_term_objective(avatar: "Avatar") -> Optional[LongTermObj
|
||||
Returns:
|
||||
生成的LongTermObjective对象,失败则返回None
|
||||
"""
|
||||
# 准备世界信息(仅获取已知区域)
|
||||
world_info = avatar.world.get_info(known_region_ids=avatar.known_regions)
|
||||
# 准备世界信息(仅获取已知区域 + 距离信息)
|
||||
world_info = avatar.world.get_info(avatar=avatar)
|
||||
|
||||
# 获取 expanded_info(包含详细信息和事件历史)
|
||||
expanded_info = avatar.get_expanded_info(detailed=True)
|
||||
|
||||
@@ -80,27 +80,44 @@ class Map():
|
||||
"""
|
||||
return self.tiles[(x, y)].region
|
||||
|
||||
def get_info(self, detailed: bool = False, known_region_ids: Optional[set[int]] = None) -> dict:
|
||||
def get_info(self, detailed: bool = False, avatar: object = None) -> dict:
|
||||
"""
|
||||
返回地图信息(dict)。
|
||||
known_region_ids: 如果提供,仅返回这些ID对应的区域信息。
|
||||
avatar: 如果提供,将用于:
|
||||
1. 过滤仅返回 avatar.known_regions 中的区域
|
||||
2. 计算并在描述中追加从 avatar 当前位置到各区域的距离
|
||||
"""
|
||||
# 动态分类(因为现在没有自动分类字典了)
|
||||
# 或者我们简单点,不分类返回,只返回总览?
|
||||
# 为了保持接口不变,我们可以现场过滤。
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
|
||||
from src.classes.region import NormalRegion, CultivateRegion, CityRegion
|
||||
from src.utils.distance import chebyshev_distance
|
||||
|
||||
known_region_ids = avatar.known_regions if avatar else None
|
||||
current_loc = (avatar.pos_x, avatar.pos_y) if avatar else None
|
||||
|
||||
def filter_regions(cls):
|
||||
return {
|
||||
rid: r for rid, r in self.regions.items()
|
||||
if rid in known_region_ids
|
||||
if known_region_ids is None or rid in known_region_ids
|
||||
}
|
||||
|
||||
def build_regions_info(regions_dict) -> list[str]:
|
||||
if detailed:
|
||||
return [r.get_detailed_info() for r in regions_dict.values()]
|
||||
return [r.get_info() for r in regions_dict.values()]
|
||||
infos = []
|
||||
for r in regions_dict.values():
|
||||
base_info = r.get_detailed_info() if detailed else r.get_info()
|
||||
|
||||
# 如果有当前位置,追加距离信息
|
||||
dist = chebyshev_distance(current_loc, r.center_loc)
|
||||
# 估算到达时间:距离 / 步长 (向上取整)
|
||||
step_len = avatar.move_step_length
|
||||
months = (dist + step_len - 1) // step_len
|
||||
# 避免显示 0 个月
|
||||
months = max(1, months)
|
||||
base_info += f"(距离:{months}月)"
|
||||
|
||||
infos.append(base_info)
|
||||
return infos
|
||||
|
||||
return {
|
||||
"修炼区域(可以修炼以增进修为)": build_regions_info(filter_regions(CultivateRegion)),
|
||||
|
||||
@@ -94,9 +94,11 @@ class Tile():
|
||||
region: 'Region' = None # 可以是一个region的一部分,也可以不属于任何region
|
||||
|
||||
|
||||
from src.utils.distance import manhattan_distance
|
||||
|
||||
def get_avatar_distance(avatar1: 'Avatar', avatar2: 'Avatar') -> int:
|
||||
"""
|
||||
计算两个 Avatar 之间的汉明距离(曼哈顿距离)
|
||||
计算两个 Avatar 之间的曼哈顿距离
|
||||
|
||||
Args:
|
||||
avatar1: 第一个角色
|
||||
@@ -105,4 +107,4 @@ def get_avatar_distance(avatar1: 'Avatar', avatar2: 'Avatar') -> int:
|
||||
Returns:
|
||||
两个角色之间的距离
|
||||
"""
|
||||
return abs(avatar1.pos_x - avatar2.pos_x) + abs(avatar1.pos_y - avatar2.pos_y)
|
||||
return manhattan_distance((avatar1.pos_x, avatar1.pos_y), (avatar2.pos_x, avatar2.pos_y))
|
||||
|
||||
@@ -23,13 +23,13 @@ class World():
|
||||
# 天地灵机开始年份(用于计算持续时间)
|
||||
phenomenon_start_year: int = 0
|
||||
|
||||
def get_info(self, detailed: bool = False, known_region_ids: Optional[set[int]] = None) -> dict:
|
||||
def get_info(self, detailed: bool = False, avatar: Optional["Avatar"] = None) -> dict:
|
||||
"""
|
||||
返回世界信息(dict),其中包含地图信息(dict)。
|
||||
如果指定了 known_region_ids,则只返回这些 ID 对应的区域信息。
|
||||
如果指定了 avatar,将传给 map.get_info 用于过滤区域和计算距离。
|
||||
"""
|
||||
static_info = self.static_info
|
||||
map_info = self.map.get_info(detailed=detailed, known_region_ids=known_region_ids)
|
||||
map_info = self.map.get_info(detailed=detailed, avatar=avatar)
|
||||
world_info = {**map_info, **static_info}
|
||||
|
||||
if self.current_phenomenon:
|
||||
|
||||
22
src/utils/distance.py
Normal file
22
src/utils/distance.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import math
|
||||
|
||||
def chebyshev_distance(p1: tuple[int, int], p2: tuple[int, int]) -> int:
|
||||
"""
|
||||
计算切比雪夫距离:max(|x1-x2|, |y1-y2|)
|
||||
适用于允许对角线移动的网格地图
|
||||
"""
|
||||
return max(abs(p1[0] - p2[0]), abs(p1[1] - p2[1]))
|
||||
|
||||
def manhattan_distance(p1: tuple[int, int], p2: tuple[int, int]) -> int:
|
||||
"""
|
||||
计算曼哈顿距离:|x1-x2| + |y1-y2|
|
||||
适用于只允许四向移动的网格地图
|
||||
"""
|
||||
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
|
||||
|
||||
def euclidean_distance(p1: tuple[int, int], p2: tuple[int, int]) -> float:
|
||||
"""
|
||||
计算欧几里得距离:sqrt((x1-x2)^2 + (y1-y2)^2)
|
||||
"""
|
||||
return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
|
||||
|
||||
@@ -56,3 +56,5 @@ id,name,exclusion_names,desc,rarity,condition,effects
|
||||
54,暗影宗师,怠惰;胆小,暗器之道登峰造极,杀人于无形。出手必见血,战力惊人,但对暗器之外的事物兴趣寥寥。,SR,,"[{when: 'avatar.weapon.type == WeaponType.HIDDEN_WEAPON', extra_weapon_proficiency_gain: 1.0, extra_battle_strength_points: 3}]"
|
||||
55,好色,无欲,你对美色有着强烈的渴求,容易被外貌出众的异性吸引,行事往往受欲望驱使。,N,,
|
||||
56,无欲,好色,你清心寡欲,对男女之事毫无兴趣,面对美色心如止水,不为所动。,N,,
|
||||
57,探险家,死宅,你对未知的世界充满好奇,热衷于探索地图上未被点亮的区域,难以忍受长时间待在同一个地方。,SR,,
|
||||
58,死宅,探险家;冒险,你认为外面的世界充满危险且麻烦,除了必要的宗门任务,你极度排斥长途跋涉,更喜欢待在熟悉的区域修炼。,N,,
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
你是一个决策者,这是一个仙侠世界,你负责来决定某角色之后的动作行为。
|
||||
角色已知的世界信息为:
|
||||
{world_info}
|
||||
全部可执行的动作有:
|
||||
{general_action_infos}
|
||||
|
||||
Reference in New Issue
Block a user