update move to region
This commit is contained in:
@@ -2,8 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from src.classes.action import DefineAction, ActualActionMixin
|
||||
from src.classes.event import Event
|
||||
from src.classes.region import Region
|
||||
from src.classes.sect import sects_by_name
|
||||
from src.classes.region import Region, resolve_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
|
||||
@@ -18,71 +17,8 @@ class MoveToRegion(DefineAction, ActualActionMixin):
|
||||
DOABLES_REQUIREMENTS = "任何时候都可以执行"
|
||||
PARAMS = {"region": "region_name"}
|
||||
|
||||
def _normalize_region_name(self, name: str) -> str:
|
||||
"""
|
||||
将诸如 "太白金府(金行灵气:10)" 归一化为 "太白金府"。
|
||||
去除常见括号及其中附加信息,并裁剪空白。
|
||||
"""
|
||||
s = name.strip()
|
||||
brackets = [("(", ")"), ("(", ")"), ("[", "]"), ("【", "】"), ("「", "」"), ("『", "』"), ("<", ">"), ("《", "》")]
|
||||
for left, right in brackets:
|
||||
# 连续移除所有成对括号内容
|
||||
while True:
|
||||
start = s.find(left)
|
||||
end = s.rfind(right)
|
||||
if start != -1 and end != -1 and end > start:
|
||||
s = (s[:start] + s[end + 1:]).strip()
|
||||
else:
|
||||
break
|
||||
return s
|
||||
|
||||
def _resolve_region(self, region: Region | str) -> Region:
|
||||
"""
|
||||
将字符串或 Region 实例解析为当前 world.map 中的 Region 实例:
|
||||
- 字符串:从 world.map.region_names 查找,不存在则抛出 ValueError
|
||||
- Region 实例:若存在 world.map.regions(按 id 索引),则按 id 映射到当前实例,否则直接返回传入实例
|
||||
"""
|
||||
if isinstance(region, str):
|
||||
region_name = region
|
||||
by_name = self.world.map.region_names
|
||||
|
||||
# 1) 精确匹配
|
||||
r = by_name.get(region_name)
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
# 2) 归一化后再精确匹配
|
||||
normalized = self._normalize_region_name(region_name)
|
||||
if normalized and normalized != region_name:
|
||||
r2 = by_name.get(normalized)
|
||||
if r2 is not None:
|
||||
return r2
|
||||
|
||||
# 3) 唯一包含匹配(当且仅当候选唯一时)
|
||||
candidates = [name for name in by_name.keys() if name and (name in region_name or (normalized and name in normalized))]
|
||||
if len(candidates) == 1:
|
||||
return by_name[candidates[0]]
|
||||
|
||||
# 4) 兜底:若传入为宗门名,则解析为其总部区域
|
||||
sect = sects_by_name.get(region_name) or (sects_by_name.get(normalized) if normalized and normalized != region_name else None)
|
||||
if sect is not None:
|
||||
# 若区域名表未命中,尝试在已注册的宗门总部区域中按 sect_name 匹配(唯一时返回)
|
||||
sect_regions = getattr(self.world.map, "sect_regions", {}) or {}
|
||||
matched = [r for r in sect_regions.values() if getattr(r, "sect_name", None) == sect.name]
|
||||
if len(matched) == 1:
|
||||
return matched[0]
|
||||
|
||||
# 失败:抛出明确错误提示
|
||||
if candidates:
|
||||
sample = ", ".join(candidates[:5])
|
||||
raise ValueError(f"区域名不唯一: {region_name},候选: {sample}")
|
||||
raise ValueError(f"未知区域名: {region_name}")
|
||||
if isinstance(region, Region):
|
||||
by_id = getattr(self.world.map, "regions", None)
|
||||
if isinstance(by_id, dict) and region.id in by_id:
|
||||
return by_id[region.id]
|
||||
return region
|
||||
raise TypeError(f"不支持的region类型: {type(region).__name__}")
|
||||
return resolve_region(self.world, region)
|
||||
|
||||
def _execute(self, region: Region | str) -> None:
|
||||
"""
|
||||
|
||||
@@ -8,6 +8,7 @@ from src.utils.config import CONFIG
|
||||
from src.classes.essence import EssenceType, Essence
|
||||
from src.classes.animal import Animal, animals_by_id
|
||||
from src.classes.plant import Plant, plants_by_id
|
||||
from src.classes.sect import sects_by_name
|
||||
|
||||
|
||||
def get_tiles_from_shape(shape: 'Shape', north_west_cor: str, south_east_cor: str) -> list[tuple[int, int]]:
|
||||
@@ -361,6 +362,80 @@ class CityRegion(Region):
|
||||
return f"{self.name} - {self.desc}"
|
||||
|
||||
|
||||
def _normalize_region_name(name: str) -> str:
|
||||
"""
|
||||
将诸如 "太白金府(金行灵气:10)" 归一化为 "太白金府":
|
||||
去除常见括号及其中附加信息,并裁剪空白。
|
||||
"""
|
||||
s = str(name).strip()
|
||||
brackets = [("(", ")"), ("(", ")"), ("[", "]"), ("【", "】"), ("「", "」"), ("『", "』"), ("<", ">"), ("《", "》")]
|
||||
for left, right in brackets:
|
||||
while True:
|
||||
start = s.find(left)
|
||||
end = s.rfind(right)
|
||||
if start != -1 and end != -1 and end > start:
|
||||
s = (s[:start] + s[end + 1:]).strip()
|
||||
else:
|
||||
break
|
||||
return s
|
||||
|
||||
|
||||
def resolve_region(world, region: Union[Region, str]) -> Region:
|
||||
"""
|
||||
解析字符串或 Region 为当前 world.map 中的 Region 实例:
|
||||
- 字符串:先精确匹配;失败则做归一化再匹配;再做“唯一包含”匹配;最后尝试按宗门名解析宗门总部区域
|
||||
- Region:若 world.map.regions 中存在同 id 的实例,则返回映射后的当前实例,否则原样返回
|
||||
|
||||
Raises:
|
||||
ValueError: 未知区域名或名称不唯一
|
||||
TypeError: 不支持的类型
|
||||
"""
|
||||
from typing import Dict # 局部导入以避免潜在循环
|
||||
|
||||
if isinstance(region, str):
|
||||
region_name = region
|
||||
by_name: Dict[str, Region] = getattr(world.map, "region_names", {})
|
||||
|
||||
# 1) 精确匹配
|
||||
r = by_name.get(region_name)
|
||||
if r is not None:
|
||||
return r
|
||||
|
||||
# 2) 归一化后再精确匹配
|
||||
normalized = _normalize_region_name(region_name)
|
||||
if normalized and normalized != region_name:
|
||||
r2 = by_name.get(normalized)
|
||||
if r2 is not None:
|
||||
return r2
|
||||
|
||||
# 3) 唯一包含匹配(当且仅当候选唯一时)
|
||||
candidates = [name for name in by_name.keys() if name and (name in region_name or (normalized and name in normalized))]
|
||||
if len(candidates) == 1:
|
||||
return by_name[candidates[0]]
|
||||
|
||||
# 4) 兜底:若传入为宗门名,则解析为其总部区域
|
||||
sect = sects_by_name.get(region_name) or (sects_by_name.get(normalized) if normalized and normalized != region_name else None)
|
||||
if sect is not None:
|
||||
sect_regions = getattr(world.map, "sect_regions", {}) or {}
|
||||
matched = [r for r in sect_regions.values() if getattr(r, "sect_name", None) == sect.name]
|
||||
if len(matched) == 1:
|
||||
return matched[0]
|
||||
|
||||
# 失败:抛出明确错误提示
|
||||
if candidates:
|
||||
sample = ", ".join(candidates[:5])
|
||||
raise ValueError(f"区域名不唯一: {region_name},候选: {sample}")
|
||||
raise ValueError(f"未知区域名: {region_name}")
|
||||
|
||||
if isinstance(region, Region):
|
||||
by_id = getattr(world.map, "regions", None)
|
||||
if isinstance(by_id, dict) and region.id in by_id:
|
||||
return by_id[region.id]
|
||||
return region
|
||||
|
||||
raise TypeError(f"不支持的region类型: {type(region).__name__}")
|
||||
|
||||
|
||||
T = TypeVar('T', NormalRegion, CultivateRegion, CityRegion)
|
||||
|
||||
def _load_regions(region_type: Type[T], config_name: str) -> tuple[dict[int, T], dict[str, T]]:
|
||||
|
||||
Reference in New Issue
Block a user