EG/plugins/user/vegetation_ecosystem/vegetation/vegetation_spawner.py
2025-12-12 16:16:15 +08:00

789 lines
28 KiB
Python

"""
植被生成器
负责根据环境条件和生态规则生成植被分布
"""
import time
from typing import Dict, Any, List, Optional, Tuple
import math
import random
class VegetationSpawner:
"""
植被生成器
负责根据环境条件、地形特征和生态规则生成植被分布
"""
def __init__(self, plugin):
"""
初始化植被生成器
Args:
plugin: 植被和生态系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 植被分布算法
self.distribution_algorithms = {
'random': {
'name': '随机分布',
'description': '完全随机的植被分布'
},
'clustered': {
'name': '聚集分布',
'description': '植被以群落形式聚集分布'
},
'gradient': {
'name': '梯度分布',
'description': '根据环境因子梯度分布植被'
},
'competitive': {
'name': '竞争分布',
'description': '考虑植物间竞争关系的分布'
},
'environmental': {
'name': '环境适应分布',
'description': '基于环境适应性的分布'
}
}
# 生成配置
self.spawn_config = {
'algorithm': 'environmental', # 默认算法
'density': 1.0, # 植被密度
'clumping_factor': 0.7, # 聚集因子
'random_seed': 12345, # 随机种子
'spawn_area': ((-100, -100), (100, 100)), # 生成区域
'max_instances': 10000 # 最大实例数
}
# 环境因子权重
self.environment_weights = {
'temperature': 0.25,
'humidity': 0.25,
'soil_fertility': 0.25,
'light_level': 0.15,
'water_level': 0.10
}
# 植被生态位偏好
self.ecological_preferences = {
'grass': {
'temperature_preference': (10, 30),
'humidity_preference': (40, 80),
'fertility_preference': (0.3, 1.0),
'light_preference': (0.5, 1.0),
'water_preference': (0.4, 0.8)
},
'bush': {
'temperature_preference': (5, 25),
'humidity_preference': (30, 70),
'fertility_preference': (0.4, 1.0),
'light_preference': (0.6, 1.0),
'water_preference': (0.3, 0.7)
},
'tree': {
'temperature_preference': (0, 30),
'humidity_preference': (40, 90),
'fertility_preference': (0.5, 1.0),
'light_preference': (0.7, 1.0),
'water_preference': (0.5, 1.0)
},
'flower': {
'temperature_preference': (15, 25),
'humidity_preference': (50, 80),
'fertility_preference': (0.6, 1.0),
'light_preference': (0.8, 1.0),
'water_preference': (0.6, 0.9)
},
'fern': {
'temperature_preference': (10, 20),
'humidity_preference': (70, 100),
'fertility_preference': (0.4, 0.8),
'light_preference': (0.2, 0.6),
'water_preference': (0.7, 1.0)
},
'cactus': {
'temperature_preference': (20, 40),
'humidity_preference': (10, 30),
'fertility_preference': (0.1, 0.5),
'light_preference': (0.8, 1.0),
'water_preference': (0.1, 0.3)
},
'moss': {
'temperature_preference': (5, 20),
'humidity_preference': (80, 100),
'fertility_preference': (0.1, 0.6),
'light_preference': (0.1, 0.4),
'water_preference': (0.8, 1.0)
},
'vine': {
'temperature_preference': (15, 30),
'humidity_preference': (60, 90),
'fertility_preference': (0.3, 0.8),
'light_preference': (0.4, 0.8),
'water_preference': (0.6, 0.9)
}
}
# 空间分布参数
self.spatial_parameters = {
'min_distance': 0.5, # 最小间距
'max_cluster_size': 10, # 最大集群大小
'cluster_radius': 5.0, # 集群半径
'edge_blending': 0.1 # 边缘混合
}
# 生成统计
self.spawn_stats = {
'total_spawned': 0,
'spawned_by_type': {},
'failed_spawns': 0,
'last_spawn_time': 0.0
}
# 生成历史
self.spawn_history = []
self.max_history_size = 100
print("✓ 植被生成器已创建")
def initialize(self) -> bool:
"""
初始化植被生成器
Returns:
是否初始化成功
"""
try:
# 初始化统计数据
if self.plugin.vegetation_manager:
veg_types = self.plugin.vegetation_manager.get_vegetation_types()
self.spawn_stats['spawned_by_type'] = {vt: 0 for vt in veg_types}
self.initialized = True
print("✓ 植被生成器初始化完成")
return True
except Exception as e:
print(f"✗ 植被生成器初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用植被生成器
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 植被生成器未初始化")
return False
self.enabled = True
print("✓ 植被生成器已启用")
return True
except Exception as e:
print(f"✗ 植被生成器启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用植被生成器"""
try:
self.enabled = False
print("✓ 植被生成器已禁用")
except Exception as e:
print(f"✗ 植被生成器禁用失败: {e}")
import traceback
traceback.print_exc()
def finalize(self):
"""清理植被生成器资源"""
try:
self.disable()
self.spawn_history.clear()
self.initialized = False
print("✓ 植被生成器资源已清理")
except Exception as e:
print(f"✗ 植被生成器资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新植被生成器状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 可以在这里添加动态生成逻辑
pass
except Exception as e:
print(f"✗ 植被生成器更新失败: {e}")
import traceback
traceback.print_exc()
def spawn_vegetation(self, area: Tuple[Tuple[float, float], Tuple[float, float]] = None,
density: float = None, algorithm: str = None) -> int:
"""
生成植被
Args:
area: 生成区域 ((min_x, min_y), (max_x, max_y))
density: 植被密度
algorithm: 生成算法
Returns:
生成的植被实例数量
"""
try:
if not self.plugin.vegetation_manager:
print("✗ 植被管理器不可用")
return 0
# 使用默认值或传入值
spawn_area = area if area else self.spawn_config['spawn_area']
spawn_density = density if density else self.spawn_config['density']
spawn_algorithm = algorithm if algorithm else self.spawn_config['algorithm']
# 检查算法有效性
if spawn_algorithm not in self.distribution_algorithms:
print(f"✗ 无效的生成算法: {spawn_algorithm}")
return 0
# 根据算法生成植被
spawned_count = 0
if spawn_algorithm == 'random':
spawned_count = self._spawn_random(spawn_area, spawn_density)
elif spawn_algorithm == 'clustered':
spawned_count = self._spawn_clustered(spawn_area, spawn_density)
elif spawn_algorithm == 'gradient':
spawned_count = self._spawn_gradient(spawn_area, spawn_density)
elif spawn_algorithm == 'competitive':
spawned_count = self._spawn_competitive(spawn_area, spawn_density)
elif spawn_algorithm == 'environmental':
spawned_count = self._spawn_environmental(spawn_area, spawn_density)
# 更新统计信息
self.spawn_stats['total_spawned'] += spawned_count
self.spawn_stats['last_spawn_time'] = time.time()
# 记录生成历史
self._record_spawn_event(spawn_algorithm, spawned_count, spawn_area)
print(f"✓ 植被生成完成: {spawned_count} 个实例,使用算法: {self.distribution_algorithms[spawn_algorithm]['name']}")
return spawned_count
except Exception as e:
print(f"✗ 植被生成失败: {e}")
import traceback
traceback.print_exc()
self.spawn_stats['failed_spawns'] += 1
return 0
def _spawn_random(self, area: Tuple[Tuple[float, float], Tuple[float, float]], density: float) -> int:
"""
随机生成植被
Args:
area: 生成区域
density: 植被密度
Returns:
生成的植被实例数量
"""
try:
(min_x, min_y), (max_x, max_y) = area
area_size = (max_x - min_x) * (max_y - min_y)
target_count = int(area_size * density * 0.1) # 调整密度系数
spawned_count = 0
veg_types = self.plugin.vegetation_manager.get_vegetation_types()
for _ in range(target_count):
if self._check_max_instances():
break
# 随机选择植被类型
veg_type = random.choice(veg_types)
# 随机生成位置
x = random.uniform(min_x, max_x)
y = 0.0 # 假设地面高度为0
z = random.uniform(min_y, max_y)
# 创建植被实例
instance_id = self.plugin.vegetation_manager.create_vegetation_instance(
veg_type, (x, y, z)
)
if instance_id >= 0:
self.spawn_stats['spawned_by_type'][veg_type] += 1
spawned_count += 1
return spawned_count
except Exception as e:
print(f"✗ 随机植被生成失败: {e}")
return 0
def _spawn_clustered(self, area: Tuple[Tuple[float, float], Tuple[float, float]], density: float) -> int:
"""
聚集生成植被
Args:
area: 生成区域
density: 植被密度
Returns:
生成的植被实例数量
"""
try:
(min_x, min_y), (max_x, max_y) = area
area_size = (max_x - min_x) * (max_y - min_y)
target_count = int(area_size * density * 0.1)
spawned_count = 0
veg_types = self.plugin.vegetation_manager.get_vegetation_types()
# 生成集群
clusters = max(1, int(target_count * (1 - self.spawn_config['clumping_factor'])))
for _ in range(clusters):
if self._check_max_instances():
break
# 随机选择集群中心
center_x = random.uniform(min_x, max_x)
center_z = random.uniform(min_y, max_y)
# 随机选择集群大小
cluster_size = random.randint(1, self.spatial_parameters['max_cluster_size'])
# 随机选择植被类型
veg_type = random.choice(veg_types)
# 在集群中心周围生成植被
for _ in range(cluster_size):
if self._check_max_instances():
break
# 在集群半径内随机生成位置
angle = random.uniform(0, 2 * math.pi)
radius = random.uniform(0, self.spatial_parameters['cluster_radius'])
x = center_x + radius * math.cos(angle)
z = center_z + radius * math.sin(angle)
# 检查是否在生成区域内
if min_x <= x <= max_x and min_y <= z <= max_y:
instance_id = self.plugin.vegetation_manager.create_vegetation_instance(
veg_type, (x, 0.0, z)
)
if instance_id >= 0:
self.spawn_stats['spawned_by_type'][veg_type] += 1
spawned_count += 1
return spawned_count
except Exception as e:
print(f"✗ 聚集植被生成失败: {e}")
return 0
def _spawn_gradient(self, area: Tuple[Tuple[float, float], Tuple[float, float]], density: float) -> int:
"""
梯度生成植被
Args:
area: 生成区域
density: 植被密度
Returns:
生成的植被实例数量
"""
try:
# 简化实现,实际中会根据环境梯度生成
return self._spawn_random(area, density)
except Exception as e:
print(f"✗ 梯度植被生成失败: {e}")
return 0
def _spawn_competitive(self, area: Tuple[Tuple[float, float], Tuple[float, float]], density: float) -> int:
"""
竞争生成植被
Args:
area: 生成区域
density: 植被密度
Returns:
生成的植被实例数量
"""
try:
# 简化实现,实际中会考虑植物间竞争关系
return self._spawn_clustered(area, density)
except Exception as e:
print(f"✗ 竞争植被生成失败: {e}")
return 0
def _spawn_environmental(self, area: Tuple[Tuple[float, float], Tuple[float, float]], density: float) -> int:
"""
环境适应生成植被
Args:
area: 生成区域
density: 植被密度
Returns:
生成的植被实例数量
"""
try:
(min_x, min_y), (max_x, max_y) = area
area_size = (max_x - min_x) * (max_y - min_y)
target_count = int(area_size * density * 0.1)
spawned_count = 0
if not self.plugin.vegetation_manager:
return 0
# 获取环境因子
environment_factors = self.plugin.vegetation_manager.get_environment_factors()
for _ in range(target_count):
if self._check_max_instances():
break
# 根据环境因子选择最适宜的植被类型
veg_type = self._select_suitable_vegetation(environment_factors)
# 随机生成位置
x = random.uniform(min_x, max_x)
z = random.uniform(min_y, max_y)
# 创建植被实例
instance_id = self.plugin.vegetation_manager.create_vegetation_instance(
veg_type, (x, 0.0, z)
)
if instance_id >= 0:
self.spawn_stats['spawned_by_type'][veg_type] += 1
spawned_count += 1
return spawned_count
except Exception as e:
print(f"✗ 环境适应植被生成失败: {e}")
return 0
def _select_suitable_vegetation(self, environment_factors: Dict[str, float]) -> str:
"""
根据环境因子选择最适宜的植被类型
Args:
environment_factors: 环境因子字典
Returns:
最适宜的植被类型
"""
try:
if not self.plugin.vegetation_manager:
veg_types = list(self.ecological_preferences.keys())
return random.choice(veg_types)
veg_types = self.plugin.vegetation_manager.get_vegetation_types()
if not veg_types:
return 'grass'
# 计算每种植被类型的适宜性评分
suitability_scores = {}
for veg_type in veg_types:
if veg_type in self.ecological_preferences:
preferences = self.ecological_preferences[veg_type]
score = self._calculate_suitability_score(environment_factors, preferences)
suitability_scores[veg_type] = score
# 选择适宜性评分最高的植被类型
if suitability_scores:
return max(suitability_scores, key=suitability_scores.get)
else:
return random.choice(veg_types)
except Exception as e:
print(f"✗ 适宜植被选择失败: {e}")
veg_types = self.plugin.vegetation_manager.get_vegetation_types() if self.plugin.vegetation_manager else ['grass']
return random.choice(veg_types)
def _calculate_suitability_score(self, environment_factors: Dict[str, float],
preferences: Dict[str, Tuple[float, float]]) -> float:
"""
计算植被类型的环境适宜性评分
Args:
environment_factors: 环境因子
preferences: 植被偏好
Returns:
适宜性评分 (0.0-1.0)
"""
try:
total_score = 0.0
weight_sum = 0.0
for factor, weight in self.environment_weights.items():
if factor in environment_factors and f"{factor}_preference" in preferences:
current_value = environment_factors[factor]
preferred_range = preferences[f"{factor}_preference"]
# 计算因子适宜性
factor_suitability = self._calculate_factor_suitability(
current_value, preferred_range
)
total_score += factor_suitability * weight
weight_sum += weight
if weight_sum > 0:
return total_score / weight_sum
return 0.5
except Exception as e:
print(f"✗ 适宜性评分计算失败: {e}")
return 0.5
def _calculate_factor_suitability(self, current_value: float, preferred_range: Tuple[float, float]) -> float:
"""
计算单个环境因子的适宜性
Args:
current_value: 当前值
preferred_range: 偏好范围
Returns:
适宜性评分 (0.0-1.0)
"""
try:
min_val, max_val = preferred_range
if min_val <= current_value <= max_val:
return 1.0
elif current_value < min_val:
if min_val > 0:
return max(0.0, 1.0 - (min_val - current_value) / min_val)
return 0.0
else: # current_value > max_val
if max_val > 0:
return max(0.0, 1.0 - (current_value - max_val) / max_val)
return 0.0
except Exception as e:
print(f"✗ 因子适宜性计算失败: {e}")
return 0.5
def _check_max_instances(self) -> bool:
"""
检查是否达到最大实例数限制
Returns:
是否达到限制
"""
try:
if self.plugin.vegetation_manager:
current_count = self.plugin.vegetation_manager.get_stats()['total_vegetation']
return current_count >= self.spawn_config['max_instances']
return False
except Exception as e:
print(f"✗ 实例数检查失败: {e}")
return False
def _record_spawn_event(self, algorithm: str, count: int, area: Tuple[Tuple[float, float], Tuple[float, float]]):
"""
记录生成事件
Args:
algorithm: 算法名称
count: 生成数量
area: 生成区域
"""
try:
event_record = {
'timestamp': time.time(),
'algorithm': algorithm,
'count': count,
'area': area
}
self.spawn_history.append(event_record)
# 限制历史记录大小
if len(self.spawn_history) > self.max_history_size:
self.spawn_history.pop(0)
except Exception as e:
print(f"✗ 生成事件记录失败: {e}")
def get_distribution_algorithms(self) -> Dict[str, Dict[str, str]]:
"""
获取可用的分布算法
Returns:
分布算法字典
"""
return self.distribution_algorithms.copy()
def set_spawn_config(self, config: Dict[str, Any]):
"""
设置生成配置
Args:
config: 配置字典
"""
try:
self.spawn_config.update(config)
print(f"✓ 生成配置已更新: {self.spawn_config}")
except Exception as e:
print(f"✗ 生成配置更新失败: {e}")
def get_spawn_config(self) -> Dict[str, Any]:
"""
获取生成配置
Returns:
生成配置字典
"""
return self.spawn_config.copy()
def set_environment_weights(self, weights: Dict[str, float]):
"""
设置环境因子权重
Args:
weights: 权重字典
"""
try:
self.environment_weights.update(weights)
print(f"✓ 环境因子权重已更新: {self.environment_weights}")
except Exception as e:
print(f"✗ 环境因子权重更新失败: {e}")
def get_environment_weights(self) -> Dict[str, float]:
"""
获取环境因子权重
Returns:
环境因子权重字典
"""
return self.environment_weights.copy()
def set_spatial_parameters(self, parameters: Dict[str, float]):
"""
设置空间分布参数
Args:
parameters: 参数字典
"""
try:
self.spatial_parameters.update(parameters)
print(f"✓ 空间分布参数已更新: {self.spatial_parameters}")
except Exception as e:
print(f"✗ 空间分布参数更新失败: {e}")
def get_spatial_parameters(self) -> Dict[str, float]:
"""
获取空间分布参数
Returns:
空间分布参数字典
"""
return self.spatial_parameters.copy()
def get_spawn_stats(self) -> Dict[str, Any]:
"""
获取生成统计信息
Returns:
生成统计信息字典
"""
return self.spawn_stats.copy()
def reset_spawn_stats(self):
"""重置生成统计信息"""
try:
self.spawn_stats = {
'total_spawned': 0,
'spawned_by_type': {},
'failed_spawns': 0,
'last_spawn_time': 0.0
}
if self.plugin.vegetation_manager:
veg_types = self.plugin.vegetation_manager.get_vegetation_types()
self.spawn_stats['spawned_by_type'] = {vt: 0 for vt in veg_types}
print("✓ 植被生成统计信息已重置")
except Exception as e:
print(f"✗ 植被生成统计信息重置失败: {e}")
def get_spawn_history(self) -> List[Dict[str, Any]]:
"""
获取生成历史
Returns:
生成历史列表
"""
return self.spawn_history.copy()
def clear_spawn_history(self):
"""清空生成历史"""
try:
self.spawn_history.clear()
print("✓ 生成历史已清空")
except Exception as e:
print(f"✗ 生成历史清空失败: {e}")
def regenerate_vegetation(self, clear_existing: bool = True) -> int:
"""
重新生成植被
Args:
clear_existing: 是否清除现有植被
Returns:
生成的植被实例数量
"""
try:
if clear_existing and self.plugin.vegetation_manager:
# 清除现有植被实例
instances = self.plugin.vegetation_manager.get_all_vegetation_instances()
for instance_id in list(instances.keys()):
self.plugin.vegetation_manager.remove_vegetation_instance(instance_id)
# 重置统计信息
self.reset_spawn_stats()
# 使用当前配置重新生成植被
spawned_count = self.spawn_vegetation()
print(f"✓ 植被重新生成完成: {spawned_count} 个实例")
return spawned_count
except Exception as e:
print(f"✗ 植被重新生成失败: {e}")
return 0