Files
cultivation-world-simulator/src/classes/map.py
2025-10-09 23:50:52 +08:00

111 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import TYPE_CHECKING, Optional
from src.classes.tile import Tile, TileType
from src.classes.sect_region import SectRegion
if TYPE_CHECKING:
from src.classes.region import Region
class Map():
"""
通过dict记录position 到 tile。
"""
def __init__(self, width: int, height: int):
self.tiles = {}
self.width = width
self.height = height
# 加载所有region数据到Map中
self._load_regions()
def _load_regions(self):
"""从配置文件加载所有区域数据到Map实例中"""
# 延迟导入避免循环导入
from src.classes.region import regions_by_id, regions_by_name
from src.classes.region import normal_regions_by_id, normal_regions_by_name
from src.classes.region import cultivate_regions_by_id, cultivate_regions_by_name
from src.classes.region import city_regions_by_id, city_regions_by_name
self.regions = regions_by_id
self.region_names = regions_by_name
self.normal_regions = normal_regions_by_id
self.normal_region_names = normal_regions_by_name
self.cultivate_regions = cultivate_regions_by_id
self.cultivate_region_names = cultivate_regions_by_name
self.city_regions = city_regions_by_id
self.city_region_names = city_regions_by_name
# 宗门总部区域集合(由地图生成阶段注入)
# 若外部未注入 SectRegion这里仍可通过 regions 过滤得到
self.sect_regions = {rid: r for rid, r in self.regions.items() if isinstance(r, SectRegion)}
def is_in_bounds(self, x: int, y: int) -> bool:
"""
判断坐标是否在地图边界内。
"""
return 0 <= x < self.width and 0 <= y < self.height
def create_tile(self, x: int, y: int, tile_type: TileType):
self.tiles[(x, y)] = Tile(tile_type, x, y, region=None)
def get_tile(self, x: int, y: int) -> Tile:
return self.tiles[(x, y)]
def get_center_locs(self, locs: list[tuple[int, int]]) -> tuple[int, int]:
"""
获取locs的中心位置。
如果几何中心恰好在位置列表中,返回几何中心;
否则返回距离几何中心最近的实际位置。
"""
if not locs:
return (0, 0)
# 分别计算x和y坐标的平均值
avg_x = sum(loc[0] for loc in locs) // len(locs)
avg_y = sum(loc[1] for loc in locs) // len(locs)
center = (avg_x, avg_y)
# 如果几何中心恰好在位置列表中,直接返回
if center in locs:
return center
# 否则找到距离几何中心最近的实际位置
def distance_squared(loc: tuple[int, int]) -> int:
"""计算到中心点的距离平方(避免开方运算)"""
return (loc[0] - avg_x) ** 2 + (loc[1] - avg_y) ** 2
return min(locs, key=distance_squared)
def get_region(self, x: int, y: int) -> Optional['Region']:
"""
获取一个region。
"""
return self.tiles[(x, y)].region
def get_info(self) -> str:
"""返回地图的简要信息,按类型分组罗列区域并说明用途。"""
parts: list[str] = []
# 修炼区域
parts.append("修炼区域(可以修炼以增进修为):")
parts.extend([f"- {str(region)}" for region in self.cultivate_regions.values()])
parts.append("")
# 普通区域
parts.append("普通区域(可以狩猎或采集):")
parts.extend([f"- {str(region)}" for region in self.normal_regions.values()])
parts.append("")
# 城市区域
parts.append("城市区域(可以交易):")
parts.extend([f"- {str(region)}" for region in self.city_regions.values()])
parts.append("")
# 宗门总部区域
if getattr(self, "sect_regions", None):
parts.append("宗门总部:")
parts.extend([f"- {region.name} - {region.desc}" for region in self.sect_regions.values()])
return "\n".join(parts)