add readme
This commit is contained in:
@@ -1,790 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import random
|
||||
import uuid
|
||||
from typing import List, Tuple, Dict, Any
|
||||
|
||||
# 将项目根目录加入 Python 路径,确保可以导入 `src` 包
|
||||
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
if PROJECT_ROOT not in sys.path:
|
||||
sys.path.insert(0, PROJECT_ROOT)
|
||||
|
||||
# 依赖项目内部模块
|
||||
from src.front.front import Front
|
||||
from src.sim.simulator import Simulator
|
||||
from src.classes.world import World
|
||||
from src.classes.tile import Map, TileType
|
||||
from src.classes.avatar import Avatar, Gender
|
||||
from src.classes.calendar import Month, Year
|
||||
from src.classes.action import Move
|
||||
from src.classes.essence import Essence, EssenceType
|
||||
from src.classes.cultivation import CultivationProgress
|
||||
from src.classes.root import Root
|
||||
from src.classes.age import Age
|
||||
|
||||
|
||||
def clamp(value: int, lo: int, hi: int) -> int:
|
||||
return max(lo, min(hi, value))
|
||||
|
||||
|
||||
def circle_points(cx: int, cy: int, r: int, width: int, height: int) -> List[Tuple[int, int]]:
|
||||
pts: List[Tuple[int, int]] = []
|
||||
r2 = r * r
|
||||
for y in range(clamp(cy - r, 0, height - 1), clamp(cy + r, 0, height - 1) + 1):
|
||||
for x in range(clamp(cx - r, 0, width - 1), clamp(cx + r, 0, width - 1) + 1):
|
||||
if (x - cx) * (x - cx) + (y - cy) * (y - cy) <= r2:
|
||||
pts.append((x, y))
|
||||
return pts
|
||||
|
||||
|
||||
def build_rich_random_map(width: int = 50, height: int = 35, *, seed: int | None = None) -> Map:
|
||||
if seed is not None:
|
||||
random.seed(seed)
|
||||
|
||||
game_map = Map(width=width, height=height)
|
||||
|
||||
# 1) 底色:平原
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
game_map.create_tile(x, y, TileType.PLAIN)
|
||||
|
||||
# 2) 西部大漠(左侧宽带),先铺设便于后续北/南带覆盖
|
||||
desert_w = max(6, width // 6) # 增加沙漠宽度
|
||||
desert_tiles: List[Tuple[int, int]] = []
|
||||
for y in range(height):
|
||||
for x in range(0, desert_w):
|
||||
game_map.create_tile(x, y, TileType.DESERT)
|
||||
desert_tiles.append((x, y))
|
||||
|
||||
# 3) 北部雪山与冰原(顶部宽带,覆盖整宽度)
|
||||
north_band = max(4, height // 6) # 增加北部带宽度
|
||||
snow_mountain_tiles: List[Tuple[int, int]] = []
|
||||
glacier_tiles: List[Tuple[int, int]] = []
|
||||
for y in range(0, north_band):
|
||||
for x in range(width):
|
||||
game_map.create_tile(x, y, TileType.SNOW_MOUNTAIN)
|
||||
snow_mountain_tiles.append((x, y))
|
||||
# 局部冰川簇
|
||||
for _ in range(random.randint(3, 5)): # 增加冰川数量
|
||||
cx = random.randint(1, width - 2)
|
||||
cy = random.randint(0, north_band - 1)
|
||||
r = random.randint(1, 3) # 增加冰川半径
|
||||
for x, y in circle_points(cx, cy, r, width, height):
|
||||
if y < north_band:
|
||||
game_map.create_tile(x, y, TileType.GLACIER)
|
||||
glacier_tiles.append((x, y))
|
||||
|
||||
# 4) 南部热带雨林(底部宽带,覆盖整宽度)
|
||||
south_band = max(4, height // 6) # 增加南部带宽度
|
||||
rainforest_tiles: List[Tuple[int, int]] = []
|
||||
for y in range(height - south_band, height):
|
||||
for x in range(width):
|
||||
game_map.create_tile(x, y, TileType.RAINFOREST)
|
||||
rainforest_tiles.append((x, y))
|
||||
|
||||
# 5) 最东海域(右侧宽带),最后铺海以覆盖前面的地形;随后在海中造岛
|
||||
sea_band_w = max(4, width // 7) # 增加海域宽度
|
||||
sea_x0 = width - sea_band_w
|
||||
sea_tiles: List[Tuple[int, int]] = []
|
||||
for y in range(height):
|
||||
for x in range(sea_x0, width):
|
||||
game_map.create_tile(x, y, TileType.SEA)
|
||||
sea_tiles.append((x, y))
|
||||
# 岛屿:在海域内生成若干小岛(平原/森林)
|
||||
for _ in range(random.randint(4, 7)): # 增加岛屿数量
|
||||
cx = random.randint(sea_x0, width - 2)
|
||||
cy = random.randint(1, height - 2)
|
||||
r = random.randint(1, 3) # 增加岛屿半径
|
||||
kind = random.choice([TileType.PLAIN, TileType.FOREST])
|
||||
for x, y in circle_points(cx, cy, r, width, height):
|
||||
if x >= sea_x0:
|
||||
game_map.create_tile(x, y, kind)
|
||||
|
||||
# 6) 若干湖泊(水域圆斑,限制在中部非海域)
|
||||
for _ in range(random.randint(4, 7)): # 增加湖泊数量
|
||||
cx = random.randint(max(2, desert_w + 1), sea_x0 - 2)
|
||||
cy = random.randint(north_band + 1, height - south_band - 2)
|
||||
r = random.randint(1, 4) # 增加湖泊半径
|
||||
for x, y in circle_points(cx, cy, r, width, height):
|
||||
if x < sea_x0:
|
||||
game_map.create_tile(x, y, TileType.WATER)
|
||||
|
||||
# 7) 中部山脉:聚集成为横向山脉群(避开海域和上下带,左移)
|
||||
mountain_tiles: List[Tuple[int, int]] = []
|
||||
# 左移山脉生成范围,从沙漠边缘开始,但不要延伸到太右边
|
||||
mountain_end_x = sea_x0 - max(5, width // 10) # 留出更多空间给东部
|
||||
|
||||
# 选择山脉中心区域,让山脉在这个区域内聚集
|
||||
mountain_center_x = (desert_w + mountain_end_x) // 2
|
||||
mountain_center_y = (north_band + height - south_band) // 2
|
||||
|
||||
# 生成多条横向山脉链,形成山脉群
|
||||
mountain_chains = random.randint(3, 5) # 3-5条山脉链
|
||||
for chain in range(mountain_chains):
|
||||
# 每条山脉链的起始位置在中心区域附近
|
||||
start_x = mountain_center_x + random.randint(-3, 3)
|
||||
start_y = mountain_center_y + random.randint(-2, 2)
|
||||
|
||||
# 山脉链长度
|
||||
chain_length = random.randint(12, 20) # 增加山脉长度
|
||||
|
||||
# 主要方向:横向为主,允许小幅上下摆动
|
||||
main_dx = 1 if random.random() < 0.5 else -1 # 主要横向方向
|
||||
main_dy = 0 # 主要垂直方向为0
|
||||
|
||||
x, y = start_x, start_y
|
||||
|
||||
for step in range(chain_length):
|
||||
if 0 <= x < mountain_end_x and north_band <= y < height - south_band:
|
||||
game_map.create_tile(x, y, TileType.MOUNTAIN)
|
||||
mountain_tiles.append((x, y))
|
||||
|
||||
# 随机添加分支山脉,增加聚集效果
|
||||
if random.random() < 0.3:
|
||||
branch_length = random.randint(2, 6)
|
||||
bx, by = x, y
|
||||
for _ in range(branch_length):
|
||||
# 分支方向:倾向于向中心聚集
|
||||
if bx < mountain_center_x:
|
||||
branch_dx = random.choice([0, 1])
|
||||
elif bx > mountain_center_x:
|
||||
branch_dx = random.choice([0, -1])
|
||||
else:
|
||||
branch_dx = random.choice([-1, 0, 1])
|
||||
|
||||
if by < mountain_center_y:
|
||||
branch_dy = random.choice([0, 1])
|
||||
elif by > mountain_center_y:
|
||||
branch_dy = random.choice([0, -1])
|
||||
else:
|
||||
branch_dy = random.choice([-1, 0, 1])
|
||||
|
||||
bx += branch_dx
|
||||
by += branch_dy
|
||||
|
||||
if (0 <= bx < mountain_end_x and north_band <= by < height - south_band and
|
||||
(bx, by) not in mountain_tiles):
|
||||
game_map.create_tile(bx, by, TileType.MOUNTAIN)
|
||||
mountain_tiles.append((bx, by))
|
||||
|
||||
# 主要方向移动
|
||||
x += main_dx
|
||||
|
||||
# 垂直方向:允许小幅摆动,但倾向于回归中心线
|
||||
if random.random() < 0.7: # 70%概率向中心回归
|
||||
if y > mountain_center_y:
|
||||
y -= 1
|
||||
elif y < mountain_center_y:
|
||||
y += 1
|
||||
else: # 30%概率随机摆动
|
||||
y += random.choice([-1, 0, 1])
|
||||
|
||||
# 确保y在有效范围内
|
||||
y = max(north_band, min(height - south_band - 1, y))
|
||||
|
||||
# 8) 中部森林:几个圆斑(调整范围与山脉一致)
|
||||
for _ in range(random.randint(5, 9)): # 增加森林数量
|
||||
cx = random.randint(desert_w + 1, mountain_end_x - 2)
|
||||
cy = random.randint(north_band + 1, height - south_band - 2)
|
||||
r = random.randint(2, 5) # 增加森林半径
|
||||
for x, y in circle_points(cx, cy, r, width, height):
|
||||
game_map.create_tile(x, y, TileType.FOREST)
|
||||
|
||||
# 8.5) 火山:在中央山脉附近生成一个火山
|
||||
volcano_tiles: List[Tuple[int, int]] = []
|
||||
# 在中央山脉的边缘附近生成火山,避免覆盖重要山脉
|
||||
# 选择山脉区域的边缘位置
|
||||
volcano_edge_choices = []
|
||||
|
||||
# 检查山脉区域的四个边缘
|
||||
if mountain_center_x > desert_w + 5: # 左边缘
|
||||
volcano_edge_choices.append((mountain_center_x - 3, mountain_center_y))
|
||||
if mountain_center_x < mountain_end_x - 5: # 右边缘
|
||||
volcano_edge_choices.append((mountain_center_x + 3, mountain_center_y))
|
||||
if mountain_center_y > north_band + 5: # 上边缘
|
||||
volcano_edge_choices.append((mountain_center_x, mountain_center_y - 3))
|
||||
if mountain_center_y < height - south_band - 5: # 下边缘
|
||||
volcano_edge_choices.append((mountain_center_x, mountain_center_y + 3))
|
||||
|
||||
# 如果没有合适的边缘位置,选择山脉区域内的非山脉位置
|
||||
if not volcano_edge_choices:
|
||||
for attempt in range(10):
|
||||
vx = mountain_center_x + random.randint(-4, 4)
|
||||
vy = mountain_center_y + random.randint(-4, 4)
|
||||
if (0 <= vx < mountain_end_x and north_band <= vy < height - south_band and
|
||||
game_map.get_tile(vx, vy).type != TileType.MOUNTAIN):
|
||||
volcano_edge_choices.append((vx, vy))
|
||||
break
|
||||
|
||||
# 如果还是没有找到合适位置,就在山脉中心附近找一个
|
||||
if not volcano_edge_choices:
|
||||
volcano_edge_choices.append((mountain_center_x, mountain_center_y))
|
||||
|
||||
# 选择火山位置
|
||||
volcano_center_x, volcano_center_y = random.choice(volcano_edge_choices)
|
||||
volcano_radius = random.randint(2, 3) # 减小火山半径
|
||||
|
||||
# 生成火山,但避免覆盖重要的山脉
|
||||
for x, y in circle_points(volcano_center_x, volcano_center_y, volcano_radius, width, height):
|
||||
if (0 <= x < mountain_end_x and north_band <= y < height - south_band):
|
||||
current_tile = game_map.get_tile(x, y)
|
||||
# 只在非山脉地形上生成火山,或者在山脉边缘生成
|
||||
if current_tile.type != TileType.MOUNTAIN or random.random() < 0.3:
|
||||
game_map.create_tile(x, y, TileType.VOLCANO)
|
||||
volcano_tiles.append((x, y))
|
||||
|
||||
# 8.6) 草原:在平原区域生成一些草原
|
||||
grassland_tiles: List[Tuple[int, int]] = []
|
||||
for _ in range(random.randint(4, 7)): # 增加草原数量
|
||||
cx = random.randint(desert_w + 1, mountain_end_x - 2)
|
||||
cy = random.randint(north_band + 1, height - south_band - 2)
|
||||
r = random.randint(2, 5) # 增加草原半径
|
||||
for x, y in circle_points(cx, cy, r, width, height):
|
||||
if x < sea_x0:
|
||||
current_tile = game_map.get_tile(x, y)
|
||||
if current_tile.type == TileType.PLAIN: # 只在平原上生成草原
|
||||
game_map.create_tile(x, y, TileType.GRASSLAND)
|
||||
grassland_tiles.append((x, y))
|
||||
|
||||
# 8.7) 沼泽:在水域附近生成一些沼泽
|
||||
swamp_tiles: List[Tuple[int, int]] = []
|
||||
for _ in range(random.randint(3, 6)): # 增加沼泽数量
|
||||
cx = random.randint(desert_w + 1, sea_x0 - 2)
|
||||
cy = random.randint(north_band + 1, height - south_band - 2)
|
||||
r = random.randint(1, 3) # 增加沼泽半径
|
||||
for x, y in circle_points(cx, cy, r, width, height):
|
||||
if x < sea_x0:
|
||||
# 检查周围是否有水域
|
||||
has_water_nearby = False
|
||||
for dx in [-1, 0, 1]:
|
||||
for dy in [-1, 0, 1]:
|
||||
nx, ny = x + dx, y + dy
|
||||
if game_map.is_in_bounds(nx, ny):
|
||||
nearby_tile = game_map.get_tile(nx, ny)
|
||||
if nearby_tile.type in (TileType.WATER, TileType.SEA):
|
||||
has_water_nearby = True
|
||||
break
|
||||
if has_water_nearby:
|
||||
break
|
||||
|
||||
if has_water_nearby:
|
||||
current_tile = game_map.get_tile(x, y)
|
||||
if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND):
|
||||
game_map.create_tile(x, y, TileType.SWAMP)
|
||||
swamp_tiles.append((x, y))
|
||||
|
||||
# 8.8) 洞穴:在山脉附近生成一些洞穴
|
||||
cave_tiles: List[Tuple[int, int]] = []
|
||||
for _ in range(random.randint(3, 6)): # 增加洞穴数量
|
||||
cx = random.randint(desert_w + 1, mountain_end_x - 1)
|
||||
cy = random.randint(north_band + 1, height - south_band - 2)
|
||||
# 检查周围是否有山脉
|
||||
has_mountain_nearby = False
|
||||
for dx in [-2, -1, 0, 1, 2]:
|
||||
for dy in [-2, -1, 0, 1, 2]:
|
||||
nx, ny = cx + dx, cy + dy
|
||||
if game_map.is_in_bounds(nx, ny):
|
||||
nearby_tile = game_map.get_tile(nx, ny)
|
||||
if nearby_tile.type == TileType.MOUNTAIN:
|
||||
has_mountain_nearby = True
|
||||
break
|
||||
if has_mountain_nearby:
|
||||
break
|
||||
|
||||
if has_mountain_nearby:
|
||||
current_tile = game_map.get_tile(cx, cy)
|
||||
if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND):
|
||||
game_map.create_tile(cx, cy, TileType.CAVE)
|
||||
cave_tiles.append((cx, cy))
|
||||
|
||||
# 8.9) 遗迹:随机在一些地方生成古代遗迹
|
||||
ruins_tiles: List[Tuple[int, int]] = []
|
||||
for _ in range(random.randint(3, 5)): # 增加遗迹数量
|
||||
cx = random.randint(desert_w + 1, sea_x0 - 2)
|
||||
cy = random.randint(north_band + 1, height - south_band - 2)
|
||||
current_tile = game_map.get_tile(cx, cy)
|
||||
if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND, TileType.DESERT):
|
||||
game_map.create_tile(cx, cy, TileType.RUINS)
|
||||
ruins_tiles.append((cx, cy))
|
||||
|
||||
# 9) 城市:2~4个,2x2格子,尽量落在非极端地形
|
||||
cities = 0
|
||||
attempts = 0
|
||||
city_positions = [] # 记录城市位置用于后续生成农田
|
||||
city_tiles = [] # 记录所有城市格子
|
||||
|
||||
while cities < random.randint(2, 4) and attempts < 300: # 增加尝试次数
|
||||
attempts += 1
|
||||
# 选择城市左上角位置
|
||||
x = random.randint(0, width - 2) # 确保有2x2的空间
|
||||
y = random.randint(0, height - 2)
|
||||
|
||||
# 检查2x2区域是否都适合建城
|
||||
can_build_city = True
|
||||
for dx in range(2):
|
||||
for dy in range(2):
|
||||
nx, ny = x + dx, y + dy
|
||||
if not game_map.is_in_bounds(nx, ny):
|
||||
can_build_city = False
|
||||
break
|
||||
t = game_map.get_tile(nx, ny)
|
||||
if t.type in (TileType.WATER, TileType.SEA, TileType.MOUNTAIN, TileType.GLACIER,
|
||||
TileType.SNOW_MOUNTAIN, TileType.DESERT, TileType.VOLCANO, TileType.SWAMP,
|
||||
TileType.CAVE, TileType.RUINS):
|
||||
can_build_city = False
|
||||
break
|
||||
if not can_build_city:
|
||||
break
|
||||
|
||||
if can_build_city:
|
||||
# 创建2x2城市
|
||||
city_tiles_for_this_city = []
|
||||
for dx in range(2):
|
||||
for dy in range(2):
|
||||
nx, ny = x + dx, y + dy
|
||||
game_map.create_tile(nx, ny, TileType.CITY)
|
||||
city_tiles_for_this_city.append((nx, ny))
|
||||
city_tiles.append((nx, ny))
|
||||
city_positions.append((x, y)) # 记录左上角位置
|
||||
cities += 1
|
||||
|
||||
# 8.10) 农田:在城市附近生成一些农田
|
||||
farm_tiles: List[Tuple[int, int]] = []
|
||||
|
||||
# 在每个城市周围生成农田
|
||||
for city_x, city_y in city_positions:
|
||||
for _ in range(random.randint(4, 8)): # 增加农田数量
|
||||
# 在城市周围3-6格范围内生成农田
|
||||
fx = city_x + random.randint(-6, 6)
|
||||
fy = city_y + random.randint(-6, 6)
|
||||
if game_map.is_in_bounds(fx, fy):
|
||||
current_tile = game_map.get_tile(fx, fy)
|
||||
if current_tile.type in (TileType.PLAIN, TileType.GRASSLAND):
|
||||
game_map.create_tile(fx, fy, TileType.FARM)
|
||||
farm_tiles.append((fx, fy))
|
||||
|
||||
# 9.5) 生成一条横贯东西的长河(允许小幅上下摆动与随机加宽,避开沙漠和大海)
|
||||
river_tiles: List[Tuple[int, int]] = []
|
||||
# 选一条靠近中部的基准纬线,避开极北/极南带
|
||||
base_y = clamp(height // 2 + random.randint(-3, 3), north_band + 2, height - south_band - 3)
|
||||
y = base_y
|
||||
|
||||
# 确保河流从西边开始,到东边结束,不断流
|
||||
for x in range(0, width):
|
||||
# 检查当前位置是否为沙漠或大海,如果是则跳过
|
||||
current_tile = game_map.get_tile(x, y)
|
||||
if current_tile.type in (TileType.DESERT, TileType.SEA):
|
||||
continue
|
||||
|
||||
# 开凿主河道
|
||||
game_map.create_tile(x, y, TileType.WATER)
|
||||
river_tiles.append((x, y))
|
||||
|
||||
# 随机加宽 1-2 格(上下其一或两个),但要避开沙漠和大海
|
||||
if random.random() < 0.6: # 增加加宽概率
|
||||
# 选择加宽方向
|
||||
wide_directions = []
|
||||
if y > 0:
|
||||
wide_tile = game_map.get_tile(x, y - 1)
|
||||
if wide_tile.type not in (TileType.DESERT, TileType.SEA):
|
||||
wide_directions.append(-1)
|
||||
if y < height - 1:
|
||||
wide_tile = game_map.get_tile(x, y + 1)
|
||||
if wide_tile.type not in (TileType.DESERT, TileType.SEA):
|
||||
wide_directions.append(1)
|
||||
|
||||
# 随机选择1-2个方向加宽
|
||||
if wide_directions:
|
||||
num_wide = random.randint(1, min(2, len(wide_directions)))
|
||||
selected_directions = random.sample(wide_directions, num_wide)
|
||||
for dy in selected_directions:
|
||||
wy = y + dy
|
||||
game_map.create_tile(x, wy, TileType.WATER)
|
||||
river_tiles.append((x, wy))
|
||||
|
||||
# 轻微摆动(-1, 0, 1),并缓慢回归基准线
|
||||
drift_choices = [-1, 0, 1]
|
||||
dy = random.choice(drift_choices)
|
||||
# 回归力:偏离过大时更倾向于向 base_y 靠拢
|
||||
if y - base_y > 3:
|
||||
dy = -1 if random.random() < 0.8 else dy
|
||||
elif base_y - y > 3:
|
||||
dy = 1 if random.random() < 0.8 else dy
|
||||
y = clamp(y + dy, north_band + 1, height - south_band - 2)
|
||||
|
||||
# 11) 聚类函数:用于后续命名山脉/森林
|
||||
def find_type_clusters(tile_type: TileType) -> list[list[Tuple[int, int]]]:
|
||||
visited: set[Tuple[int, int]] = set()
|
||||
clusters: list[list[Tuple[int, int]]] = []
|
||||
for (tx, ty), t in game_map.tiles.items():
|
||||
if t.type is not tile_type or (tx, ty) in visited:
|
||||
continue
|
||||
stack = [(tx, ty)]
|
||||
visited.add((tx, ty))
|
||||
comp: list[Tuple[int, int]] = []
|
||||
while stack:
|
||||
cx, cy = stack.pop()
|
||||
comp.append((cx, cy))
|
||||
for nx, ny in ((cx + 1, cy), (cx - 1, cy), (cx, cy + 1), (cx, cy - 1)):
|
||||
if not game_map.is_in_bounds(nx, ny) or (nx, ny) in visited:
|
||||
continue
|
||||
tt = game_map.get_tile(nx, ny)
|
||||
if tt.type is tile_type:
|
||||
visited.add((nx, ny))
|
||||
stack.append((nx, ny))
|
||||
clusters.append(comp)
|
||||
return clusters
|
||||
|
||||
# 高山:阈值较低,便于更多命名;森林:阈值更高,避免碎片
|
||||
all_mountain_clusters = find_type_clusters(TileType.MOUNTAIN)
|
||||
mountain_clusters = [c for c in all_mountain_clusters if len(c) >= 8]
|
||||
forest_clusters = [c for c in find_type_clusters(TileType.FOREST) if len(c) >= 12]
|
||||
|
||||
# 组装所有地理信息到一个统一的配置 dict
|
||||
regions_cfg: List[Dict[str, Any]] = []
|
||||
if desert_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "大漠",
|
||||
"description": "西部荒漠地带",
|
||||
"essence": Essence(density={
|
||||
EssenceType.EARTH: 8,
|
||||
EssenceType.FIRE: 6,
|
||||
EssenceType.GOLD: 4,
|
||||
EssenceType.WOOD: 2,
|
||||
EssenceType.WATER: 1
|
||||
}),
|
||||
"tiles": desert_tiles
|
||||
})
|
||||
if sea_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "东海",
|
||||
"description": "最东边的大海",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WATER: 10,
|
||||
EssenceType.EARTH: 3,
|
||||
EssenceType.GOLD: 2,
|
||||
EssenceType.WOOD: 1,
|
||||
EssenceType.FIRE: 1
|
||||
}),
|
||||
"tiles": sea_tiles
|
||||
})
|
||||
if rainforest_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "南疆雨林",
|
||||
"description": "南部潮湿炎热的雨林",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WOOD: 9,
|
||||
EssenceType.WATER: 7,
|
||||
EssenceType.FIRE: 5,
|
||||
EssenceType.EARTH: 3,
|
||||
EssenceType.GOLD: 2
|
||||
}),
|
||||
"tiles": rainforest_tiles
|
||||
})
|
||||
if river_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "大河",
|
||||
"description": "发源内陆,奔流入海",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WATER: 8,
|
||||
EssenceType.EARTH: 4,
|
||||
EssenceType.WOOD: 3,
|
||||
EssenceType.GOLD: 2,
|
||||
EssenceType.FIRE: 1
|
||||
}),
|
||||
"tiles": river_tiles
|
||||
})
|
||||
|
||||
# 添加山脉region(提高金属性灵气)
|
||||
if mountain_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "中央山脉",
|
||||
"description": "横贯大陆的中央山脉,蕴含丰富的金属性灵气",
|
||||
"essence": Essence(density={
|
||||
EssenceType.GOLD: 10, # 提高金属性灵气
|
||||
EssenceType.EARTH: 9,
|
||||
EssenceType.FIRE: 5,
|
||||
EssenceType.WATER: 3,
|
||||
EssenceType.WOOD: 2
|
||||
}),
|
||||
"tiles": mountain_tiles
|
||||
})
|
||||
|
||||
# 添加雪山region
|
||||
if snow_mountain_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "北境雪山",
|
||||
"description": "北部终年积雪的高山地带",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WATER: 9,
|
||||
EssenceType.EARTH: 8,
|
||||
EssenceType.GOLD: 6,
|
||||
EssenceType.FIRE: 2,
|
||||
EssenceType.WOOD: 1
|
||||
}),
|
||||
"tiles": snow_mountain_tiles
|
||||
})
|
||||
|
||||
# 添加冰川region
|
||||
if glacier_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "极地冰川",
|
||||
"description": "北部极寒的冰川地带",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WATER: 10,
|
||||
EssenceType.EARTH: 7,
|
||||
EssenceType.GOLD: 5,
|
||||
EssenceType.FIRE: 1,
|
||||
EssenceType.WOOD: 1
|
||||
}),
|
||||
"tiles": glacier_tiles
|
||||
})
|
||||
|
||||
# 添加火山region(火属性灵气最高)
|
||||
if volcano_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "火山",
|
||||
"description": "活跃的火山地带,火属性灵气极其浓郁",
|
||||
"essence": Essence(density={
|
||||
EssenceType.FIRE: 10, # 火属性灵气最高
|
||||
EssenceType.EARTH: 8,
|
||||
EssenceType.GOLD: 6,
|
||||
EssenceType.WATER: 2,
|
||||
EssenceType.WOOD: 1
|
||||
}),
|
||||
"tiles": volcano_tiles
|
||||
})
|
||||
|
||||
# 添加草原region
|
||||
if grassland_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "青青草原",
|
||||
"description": "广阔的草原地带,适合放牧和修炼",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WOOD: 7,
|
||||
EssenceType.EARTH: 6,
|
||||
EssenceType.WATER: 5,
|
||||
EssenceType.FIRE: 3,
|
||||
EssenceType.GOLD: 2
|
||||
}),
|
||||
"tiles": grassland_tiles
|
||||
})
|
||||
|
||||
# 添加沼泽region
|
||||
if swamp_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "迷雾沼泽",
|
||||
"description": "危险的沼泽地带,瘴气弥漫但蕴含特殊灵药",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WATER: 8,
|
||||
EssenceType.WOOD: 6,
|
||||
EssenceType.EARTH: 5,
|
||||
EssenceType.FIRE: 3,
|
||||
EssenceType.GOLD: 2
|
||||
}),
|
||||
"tiles": swamp_tiles
|
||||
})
|
||||
|
||||
# 添加洞穴region
|
||||
if cave_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "神秘洞穴",
|
||||
"description": "隐藏在山脉中的神秘洞穴,可能藏有宝物",
|
||||
"essence": Essence(density={
|
||||
EssenceType.EARTH: 9,
|
||||
EssenceType.GOLD: 8,
|
||||
EssenceType.FIRE: 4,
|
||||
EssenceType.WATER: 3,
|
||||
EssenceType.WOOD: 2
|
||||
}),
|
||||
"tiles": cave_tiles
|
||||
})
|
||||
|
||||
# 添加遗迹region
|
||||
if ruins_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "古代遗迹",
|
||||
"description": "上古时代留下的神秘遗迹,蕴含古老的力量",
|
||||
"essence": Essence(density={
|
||||
EssenceType.GOLD: 9,
|
||||
EssenceType.EARTH: 7,
|
||||
EssenceType.FIRE: 6,
|
||||
EssenceType.WATER: 5,
|
||||
EssenceType.WOOD: 4
|
||||
}),
|
||||
"tiles": ruins_tiles
|
||||
})
|
||||
|
||||
# 添加农田region
|
||||
if farm_tiles:
|
||||
regions_cfg.append({
|
||||
"name": "良田",
|
||||
"description": "肥沃的农田,为城市提供粮食",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WOOD: 8,
|
||||
EssenceType.EARTH: 7,
|
||||
EssenceType.WATER: 6,
|
||||
EssenceType.FIRE: 3,
|
||||
EssenceType.GOLD: 2
|
||||
}),
|
||||
"tiles": farm_tiles
|
||||
})
|
||||
|
||||
# 添加城市region
|
||||
if city_tiles:
|
||||
# 为每个城市创建单独的region
|
||||
city_names = ["长安", "洛阳", "建康", "临安", "大都", "金陵", "燕京", "成都"]
|
||||
city_name_index = 0
|
||||
|
||||
# 按城市位置分组
|
||||
city_groups = []
|
||||
used_positions = set()
|
||||
|
||||
for city_x, city_y in city_positions:
|
||||
if (city_x, city_y) not in used_positions:
|
||||
# 收集这个2x2城市的所有格子
|
||||
city_group = []
|
||||
for dx in range(2):
|
||||
for dy in range(2):
|
||||
nx, ny = city_x + dx, city_y + dy
|
||||
city_group.append((nx, ny))
|
||||
used_positions.add((nx, ny))
|
||||
city_groups.append(city_group)
|
||||
|
||||
# 为每个城市创建region
|
||||
for i, city_group in enumerate(city_groups):
|
||||
if i < len(city_names):
|
||||
city_name = city_names[i]
|
||||
else:
|
||||
city_name = f"城市{i+1}"
|
||||
|
||||
regions_cfg.append({
|
||||
"name": city_name,
|
||||
"description": f"繁华的都市,人口密集,商业繁荣",
|
||||
"essence": Essence(density={
|
||||
EssenceType.GOLD: 9, # 城市金属性灵气最高
|
||||
EssenceType.FIRE: 8, # 火属性(人气)也很高
|
||||
EssenceType.EARTH: 7,
|
||||
EssenceType.WOOD: 6,
|
||||
EssenceType.WATER: 5
|
||||
}),
|
||||
"tiles": city_group
|
||||
})
|
||||
|
||||
for i, comp in enumerate(sorted(mountain_clusters, key=len, reverse=True), start=1):
|
||||
regions_cfg.append({
|
||||
"name": f"高山{i}",
|
||||
"description": "山脉与高峰地带",
|
||||
"essence": Essence(density={
|
||||
EssenceType.EARTH: 9,
|
||||
EssenceType.GOLD: 7,
|
||||
EssenceType.FIRE: 4,
|
||||
EssenceType.WATER: 3,
|
||||
EssenceType.WOOD: 2
|
||||
}),
|
||||
"tiles": comp
|
||||
})
|
||||
for i, comp in enumerate(sorted(forest_clusters, key=len, reverse=True), start=1):
|
||||
regions_cfg.append({
|
||||
"name": f"大林{i}",
|
||||
"description": "茂密幽深的森林",
|
||||
"essence": Essence(density={
|
||||
EssenceType.WOOD: 8,
|
||||
EssenceType.EARTH: 5,
|
||||
EssenceType.WATER: 4,
|
||||
EssenceType.FIRE: 2,
|
||||
EssenceType.GOLD: 1
|
||||
}),
|
||||
"tiles": comp
|
||||
})
|
||||
|
||||
# 应用配置创建 Region,并把配置存到 map 上,方便前端/后续逻辑使用
|
||||
for r in regions_cfg:
|
||||
game_map.create_region(r["name"], r["description"], r["essence"], r["tiles"])
|
||||
geo_config: Dict[str, Any] = {"regions": regions_cfg}
|
||||
setattr(game_map, "geo_config", geo_config)
|
||||
|
||||
return game_map
|
||||
|
||||
|
||||
def random_gender() -> Gender:
|
||||
return Gender.MALE if random.random() < 0.5 else Gender.FEMALE
|
||||
|
||||
|
||||
def make_avatars(world: World, count: int = 12, current_year: Year = Year(100)) -> dict[str, Avatar]:
|
||||
avatars: dict[str, Avatar] = {}
|
||||
width, height = world.map.width, world.map.height
|
||||
for i in range(count):
|
||||
name = f"NPC{i+1:03d}"
|
||||
# 随机生成年龄,范围从16到60岁
|
||||
age_years = random.randint(16, 60)
|
||||
# 根据当前年份和年龄计算出生年份
|
||||
birth_year = current_year - age_years
|
||||
birth_month = random.choice(list(Month))
|
||||
gender = random_gender()
|
||||
|
||||
# 随机生成level,范围从0到120(对应四个大境界)
|
||||
level = random.randint(0, 120)
|
||||
cultivation_progress = CultivationProgress(level)
|
||||
|
||||
# 创建Age实例,传入年龄
|
||||
age = Age(age_years)
|
||||
|
||||
# 找一个非海域的出生点
|
||||
for _ in range(200):
|
||||
x = random.randint(0, width - 1)
|
||||
y = random.randint(0, height - 1)
|
||||
t = world.map.get_tile(x, y)
|
||||
if t.type not in (TileType.WATER, TileType.SEA, TileType.MOUNTAIN, TileType.VOLCANO, TileType.SWAMP, TileType.CAVE, TileType.RUINS):
|
||||
break
|
||||
else:
|
||||
x, y = random.randint(0, width - 1), random.randint(0, height - 1)
|
||||
|
||||
avatar = Avatar(
|
||||
world=world,
|
||||
name=name,
|
||||
id=str(uuid.uuid4()),
|
||||
birth_month=birth_month,
|
||||
birth_year=birth_year,
|
||||
age=age,
|
||||
gender=gender,
|
||||
cultivation_progress=cultivation_progress,
|
||||
pos_x=x,
|
||||
pos_y=y,
|
||||
root=random.choice(list(Root)), # 随机选择灵根
|
||||
)
|
||||
avatar.tile = world.map.get_tile(x, y)
|
||||
avatars[avatar.id] = avatar
|
||||
return avatars
|
||||
|
||||
|
||||
def main():
|
||||
# 为了每次更丰富,使用随机种子;如需复现可将 seed 固定
|
||||
# random.seed(42)
|
||||
|
||||
width, height = 50, 35 # 使用新的默认尺寸
|
||||
game_map = build_rich_random_map(width=width, height=height)
|
||||
world = World(map=game_map)
|
||||
|
||||
# 设置模拟器从第100年开始
|
||||
sim = Simulator(world)
|
||||
sim.year = Year(100) # 设置初始年份为100年
|
||||
sim.month = Month.JANUARY # 设置初始月份为1月
|
||||
|
||||
# 创建角色,传入当前年份确保年龄与生日匹配
|
||||
sim.avatars.update(make_avatars(world, count=14, current_year=sim.year))
|
||||
|
||||
front = Front(
|
||||
simulator=sim,
|
||||
tile_size=24, # 稍微减小tile大小以适应更大的地图
|
||||
margin=8,
|
||||
step_interval_ms=350,
|
||||
window_title="Cultivation World — Front Demo",
|
||||
sidebar_width=350, # 新增:设置侧边栏宽度
|
||||
)
|
||||
front.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user