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:

22
src/utils/distance.py Normal file
View 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)

View File

@@ -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 id name exclusion_names desc rarity condition effects
56 54 暗影宗师 怠惰;胆小 暗器之道登峰造极,杀人于无形。出手必见血,战力惊人,但对暗器之外的事物兴趣寥寥。 SR [{when: 'avatar.weapon.type == WeaponType.HIDDEN_WEAPON', extra_weapon_proficiency_gain: 1.0, extra_battle_strength_points: 3}]
57 55 好色 无欲 你对美色有着强烈的渴求,容易被外貌出众的异性吸引,行事往往受欲望驱使。 N
58 56 无欲 好色 你清心寡欲,对男女之事毫无兴趣,面对美色心如止水,不为所动。 N
59 57 探险家 死宅 你对未知的世界充满好奇,热衷于探索地图上未被点亮的区域,难以忍受长时间待在同一个地方。 SR
60 58 死宅 探险家;冒险 你认为外面的世界充满危险且麻烦,除了必要的宗门任务,你极度排斥长途跋涉,更喜欢待在熟悉的区域修炼。 N

View File

@@ -1,4 +1,5 @@
你是一个决策者,这是一个仙侠世界,你负责来决定某角色之后的动作行为。
角色已知的世界信息为:
{world_info}
全部可执行的动作有:
{general_action_infos}