update move

This commit is contained in:
bridge
2025-10-10 00:28:52 +08:00
parent c982996509
commit 6ecf8cc18f
7 changed files with 98 additions and 39 deletions

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
from src.classes.action import DefineAction, ChunkActionMixin
from src.classes.action.move_helper import clamp_manhattan_with_diagonal_priority
class Move(DefineAction, ChunkActionMixin):
@@ -16,10 +17,9 @@ class Move(DefineAction, ChunkActionMixin):
移动到某个tile
"""
world = self.world
# 基于境界的移动步长:每轴最多移动 move_step_length 格
# 基于境界的移动步长:曼哈顿限制,优先斜向
step = getattr(self.avatar, "move_step_length", 1)
clamped_dx = max(-step, min(step, delta_x))
clamped_dy = max(-step, min(step, delta_y))
clamped_dx, clamped_dy = clamp_manhattan_with_diagonal_priority(delta_x, delta_y, step)
new_x = self.avatar.pos_x + clamped_dx
new_y = self.avatar.pos_y + clamped_dy

View File

@@ -1,7 +1,12 @@
from __future__ import annotations
from src.classes.action import TimedAction
from src.classes.action import TimedAction, Move
from src.classes.event import Event
from src.classes.action.move_helper import clamp_manhattan_with_diagonal_priority
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from src.classes.avatar import Avatar
class MoveAwayFromAvatar(TimedAction):
@@ -15,7 +20,7 @@ class MoveAwayFromAvatar(TimedAction):
DOABLES_REQUIREMENTS = "任何时候都可以执行"
PARAMS = {"avatar_name": "AvatarName"}
def _find_avatar_by_name(self, name: str) -> "Avatar|None":
def _find_avatar_by_name(self, name: str) -> "Avatar | None":
for v in self.world.avatar_manager.avatars.values():
if v.name == name:
return v
@@ -27,15 +32,12 @@ class MoveAwayFromAvatar(TimedAction):
target = self._find_avatar_by_name(avatar_name)
if target is None:
return
# 计算远离方向:使曼哈顿距离尽量增大
dx = 1 if self.avatar.pos_x >= target.pos_x else -1
dy = 1 if self.avatar.pos_y >= target.pos_y else -1
nx = self.avatar.pos_x + dx
ny = self.avatar.pos_y + dy
if self.world.map.is_in_bounds(nx, ny):
self.avatar.pos_x = nx
self.avatar.pos_y = ny
self.avatar.tile = self.world.map.get_tile(nx, ny)
# 远离方向:以目标到自身的向量取反
raw_dx = -(target.pos_x - self.avatar.pos_x)
raw_dy = -(target.pos_y - self.avatar.pos_y)
step = getattr(self.avatar, "move_step_length", 1)
dx, dy = clamp_manhattan_with_diagonal_priority(raw_dx, raw_dy, step)
Move(self.avatar, self.world).execute(dx, dy)
def can_start(self, avatar_name: str | None = None) -> bool:
return True

View File

@@ -1,7 +1,8 @@
from __future__ import annotations
from src.classes.action import InstantAction
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
class MoveAwayFromRegion(InstantAction):
@@ -10,15 +11,26 @@ class MoveAwayFromRegion(InstantAction):
PARAMS = {"region": "RegionName"}
def _execute(self, region: str) -> None:
# 简化:向地图边缘移动一步
dx = 1 if self.avatar.pos_x < self.world.map.width - 1 else -1
dy = 1 if self.avatar.pos_y < self.world.map.height - 1 else -1
nx = max(0, min(self.world.map.width - 1, self.avatar.pos_x + dx))
ny = max(0, min(self.world.map.height - 1, self.avatar.pos_y + dy))
if self.world.map.is_in_bounds(nx, ny):
self.avatar.pos_x = nx
self.avatar.pos_y = ny
self.avatar.tile = self.world.map.get_tile(nx, ny)
# 策略:朝最近的边界方向移动,曼哈顿步长限制,优先斜向
width = self.world.map.width
height = self.world.map.height
x = self.avatar.pos_x
y = self.avatar.pos_y
# 离四边的距离
dist_left = x
dist_right = width - 1 - x
dist_top = y
dist_bottom = height - 1 - y
# 选择更近的两个边界方向组成一个大致“远离区域”的方向
# 简化:朝左右中更近的一侧+上下中更近的一侧移动
dir_x = -1 if dist_left < dist_right else (1 if dist_right < dist_left else 0)
dir_y = -1 if dist_top < dist_bottom else (1 if dist_bottom < dist_top else 0)
step = getattr(self.avatar, "move_step_length", 1)
dx, dy = clamp_manhattan_with_diagonal_priority(dir_x * step, dir_y * step, step)
Move(self.avatar, self.world).execute(dx, dy)
def can_start(self, region: str | None = None) -> bool:
return True

View File

@@ -0,0 +1,46 @@
from __future__ import annotations
def clamp_manhattan_with_diagonal_priority(dx: int, dy: int, step: int) -> tuple[int, int]:
"""
在不超过给定曼哈顿步长 step 的前提下,对 (dx, dy) 进行裁剪,且优先斜向移动。
规则:
- 返回的 (mx, my) 满足 |mx| + |my| <= step
- 每轴不超过原目标量:|mx| <= |dx|, |my| <= |dy|
- 优先分配斜向步(即同时占用 x 与 y 各 1 步),其后再把剩余步数分配给剩余距离更大的轴
- 保持原方向(符号)
"""
if step <= 0 or (dx == 0 and dy == 0):
return 0, 0
abs_dx = abs(dx)
abs_dy = abs(dy)
sign_x = 1 if dx > 0 else (-1 if dx < 0 else 0)
sign_y = 1 if dy > 0 else (-1 if dy < 0 else 0)
# 实际可用预算不超过所需的曼哈顿距离
budget = min(step, abs_dx + abs_dy)
# 先分配尽量多的斜向步:每个斜向步消耗 2 点预算
diagonal_steps = min(min(abs_dx, abs_dy), budget // 2)
move_x = diagonal_steps
move_y = diagonal_steps
remaining = budget - 2 * diagonal_steps
# 若还有剩余预算,分配给剩余距离更大的轴
rem_x = abs_dx - move_x
rem_y = abs_dy - move_y
if remaining > 0:
if rem_x >= rem_y:
add_x = min(remaining, rem_x)
move_x += add_x
remaining -= add_x
if remaining > 0:
add_y = min(remaining, rem_y)
move_y += add_y
return move_x * sign_x, move_y * sign_y

View File

@@ -4,6 +4,7 @@ from src.classes.action import DefineAction, ActualActionMixin
from src.classes.event import Event
from src.classes.action import Move
from src.classes.action_runtime import ActionResult, ActionStatus
from src.classes.action.move_helper import clamp_manhattan_with_diagonal_priority
class MoveToAvatar(DefineAction, ActualActionMixin):
@@ -30,12 +31,11 @@ class MoveToAvatar(DefineAction, ActualActionMixin):
return
cur_loc = (self.avatar.pos_x, self.avatar.pos_y)
target_loc = (target.pos_x, target.pos_y)
delta_x = target_loc[0] - cur_loc[0]
delta_y = target_loc[1] - cur_loc[1]
raw_dx = target_loc[0] - cur_loc[0]
raw_dy = target_loc[1] - cur_loc[1]
step = getattr(self.avatar, "move_step_length", 1)
delta_x = max(-step, min(step, delta_x))
delta_y = max(-step, min(step, delta_y))
Move(self.avatar, self.world).execute(delta_x, delta_y)
dx, dy = clamp_manhattan_with_diagonal_priority(raw_dx, raw_dy, step)
Move(self.avatar, self.world).execute(dx, dy)
def can_start(self, avatar_name: str | None = None) -> bool:
return True

View File

@@ -5,6 +5,7 @@ from src.classes.event import Event
from src.classes.region import Region
from src.classes.action import Move
from src.classes.action_runtime import ActionResult, ActionStatus
from src.classes.action.move_helper import clamp_manhattan_with_diagonal_priority
class MoveToRegion(DefineAction, ActualActionMixin):
@@ -41,13 +42,11 @@ class MoveToRegion(DefineAction, ActualActionMixin):
region = self._resolve_region(region)
cur_loc = (self.avatar.pos_x, self.avatar.pos_y)
region_center_loc = region.center_loc
delta_x = region_center_loc[0] - cur_loc[0]
delta_y = region_center_loc[1] - cur_loc[1]
# 横纵向一次最多移动 move_step_length 格(可以同时横纵移动)
raw_dx = region_center_loc[0] - cur_loc[0]
raw_dy = region_center_loc[1] - cur_loc[1]
step = getattr(self.avatar, "move_step_length", 1)
delta_x = max(-step, min(step, delta_x))
delta_y = max(-step, min(step, delta_y))
Move(self.avatar, self.world).execute(delta_x, delta_y)
dx, dy = clamp_manhattan_with_diagonal_priority(raw_dx, raw_dy, step)
Move(self.avatar, self.world).execute(dx, dy)
def can_start(self, region: Region | str | None = None) -> bool:
return True

View File

@@ -41,10 +41,10 @@ LEVELS_PER_REALM = 30
LEVELS_PER_STAGE = 10
REALM_TO_MOVE_STEP = {
Realm.Qi_Refinement: 1,
Realm.Foundation_Establishment: 2,
Realm.Core_Formation: 2,
Realm.Nascent_Soul: 2,
Realm.Qi_Refinement: 2,
Realm.Foundation_Establishment: 3,
Realm.Core_Formation: 4,
Realm.Nascent_Soul: 5,
}
class CultivationProgress: