update distance

This commit is contained in:
bridge
2025-12-08 22:39:44 +08:00
parent 303bffe413
commit 8124537cff
10 changed files with 66 additions and 21 deletions

View File

@@ -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:

View File

@@ -0,0 +1 @@

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)),

View File

@@ -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))

View File

@@ -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: