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

750 lines
26 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.

"""
动物模拟器
负责模拟动物种群行为和与植被的相互作用
"""
import time
from typing import Dict, Any, List, Optional
import math
import random
class AnimalSimulator:
"""
动物模拟器
负责模拟动物种群行为、繁殖、死亡和与植被的相互作用
"""
def __init__(self, plugin):
"""
初始化动物模拟器
Args:
plugin: 植被和生态系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 动物种类定义
self.animal_species = {
'rabbit': {
'name': '兔子',
'description': '草食性小型哺乳动物,优秀的种子传播者',
'diet': 'herbivore',
'size': 'small',
'reproduction_rate': 0.3, # 每天繁殖率
'mortality_rate': 0.02, # 每天死亡率
'mobility': 0.8, # 移动能力
'preferred_food': ['grass', 'flower'],
'territory_size': 10.0,
'lifespan': 365, # 天
'max_population': 50,
'pollinator': False,
'seed_disperser': True
},
'deer': {
'name': '鹿',
'description': '草食性中型哺乳动物,重要的种子传播者',
'diet': 'herbivore',
'size': 'medium',
'reproduction_rate': 0.05,
'mortality_rate': 0.01,
'mobility': 0.9,
'preferred_food': ['bush', 'tree', 'grass'],
'territory_size': 50.0,
'lifespan': 2190, # 6年
'max_population': 20,
'pollinator': False,
'seed_disperser': True
},
'wolf': {
'name': '',
'description': '肉食性大型哺乳动物,顶级捕食者',
'diet': 'carnivore',
'size': 'large',
'reproduction_rate': 0.02,
'mortality_rate': 0.005,
'mobility': 0.95,
'preferred_food': ['rabbit', 'deer'],
'territory_size': 100.0,
'lifespan': 2555, # 7年
'max_population': 10,
'pollinator': False,
'seed_disperser': False
},
'fox': {
'name': '狐狸',
'description': '杂食性小型哺乳动物',
'diet': 'omnivore',
'size': 'small',
'reproduction_rate': 0.1,
'mortality_rate': 0.015,
'mobility': 0.85,
'preferred_food': ['rabbit', 'flower', 'berry'],
'territory_size': 30.0,
'lifespan': 1460, # 4年
'max_population': 15,
'pollinator': False,
'seed_disperser': True
},
'bird': {
'name': '鸟类',
'description': '飞行动物,重要的授粉者和种子传播者',
'diet': 'omnivore',
'size': 'small',
'reproduction_rate': 0.2,
'mortality_rate': 0.03,
'mobility': 1.0,
'preferred_food': ['flower', 'berry', 'insect'],
'territory_size': 200.0,
'lifespan': 1095, # 3年
'max_population': 30,
'pollinator': True,
'seed_disperser': True
},
'insect': {
'name': '昆虫',
'description': '小型无脊椎动物,主要授粉者',
'diet': 'omnivore',
'size': 'tiny',
'reproduction_rate': 0.5,
'mortality_rate': 0.1,
'mobility': 0.7,
'preferred_food': ['flower', 'fruit', 'decaying_matter'],
'territory_size': 1.0,
'lifespan': 30, # 1个月
'max_population': 500,
'pollinator': True,
'seed_disperser': False
}
}
# 动物种群
self.animal_populations = {}
self.population_counter = 0
# 动物行为配置
self.behavior_config = {
'feeding_efficiency': 0.8, # 进食效率
'energy_consumption': 0.1, # 能量消耗率
'migration_probability': 0.05, # 迁移概率
'social_behavior': 0.7, # 社会行为倾向
'fear_factor': 0.6, # 恐惧因子
'territory_awareness': 0.8 # 领域意识
}
# 环境影响因子
self.environment_factors = {
'temperature': 20.0,
'humidity': 60.0,
'vegetation_density': 0.5,
'water_availability': 0.7,
'predator_presence': 0.2
}
# 动物实例
self.animal_instances = {}
self.instance_counter = 0
# 动物状态跟踪
self.animal_states = {
'feeding': [], # 正在进食的动物
'moving': [], # 正在移动的动物
'resting': [], # 正在休息的动物
'mating': [] # 正在交配的动物
}
# 统计信息
self.stats = {
'total_animals': 0,
'animals_by_species': {},
'births': 0,
'deaths': 0,
'feedings': 0,
'movements': 0
}
print("✓ 动物模拟器已创建")
def initialize(self) -> bool:
"""
初始化动物模拟器
Returns:
是否初始化成功
"""
try:
# 初始化统计数据
self.stats['animals_by_species'] = {species: 0 for species in self.animal_species.keys()}
# 初始化一些动物种群
self._initialize_populations()
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.animal_populations.clear()
self.animal_instances.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
# 更新动物种群
self._update_populations(dt)
# 更新动物实例
self._update_animal_instances(dt)
# 更新动物行为
self._update_animal_behaviors(dt)
except Exception as e:
print(f"✗ 动物模拟器更新失败: {e}")
import traceback
traceback.print_exc()
def _initialize_populations(self):
"""初始化动物种群"""
try:
# 为每种动物创建初始种群
for species_name in self.animal_species.keys():
population_id = self.population_counter
self.population_counter += 1
initial_size = max(2, int(self.animal_species[species_name]['max_population'] * 0.1))
population_data = {
'id': population_id,
'species': species_name,
'size': initial_size,
'health': 0.8,
'territory_center': (random.uniform(-50, 50), random.uniform(-50, 50)),
'last_update': time.time(),
'creation_time': time.time()
}
self.animal_populations[population_id] = population_data
# 更新统计数据
self.stats['animals_by_species'][species_name] += initial_size
self.stats['total_animals'] += initial_size
print(f"{self.animal_species[species_name]['name']} 种群已初始化,大小: {initial_size}")
except Exception as e:
print(f"✗ 动物种群初始化失败: {e}")
def _update_populations(self, dt: float):
"""
更新动物种群
Args:
dt: 时间增量
"""
try:
populations_to_remove = []
for population_id, population in self.animal_populations.items():
species_name = population['species']
species_info = self.animal_species[species_name]
# 计算繁殖和死亡
current_size = population['size']
# 繁殖
reproduction_rate = species_info['reproduction_rate']
births = int(current_size * reproduction_rate * dt / 86400) # 转换为天
# 死亡
mortality_rate = species_info['mortality_rate']
deaths = int(current_size * mortality_rate * dt / 86400)
# 环境压力影响
environment_pressure = 1.0 - self._calculate_environment_suitability(species_name)
deaths += int(current_size * environment_pressure * 0.1)
# 更新种群大小
new_size = max(0, current_size + births - deaths)
population['size'] = min(new_size, species_info['max_population'])
# 更新统计数据
size_change = population['size'] - current_size
self.stats['total_animals'] += size_change
self.stats['animals_by_species'][species_name] += size_change
self.stats['births'] += births
self.stats['deaths'] += deaths
# 如果种群灭绝,标记移除
if population['size'] <= 0:
populations_to_remove.append(population_id)
# 移除灭绝的种群
for population_id in populations_to_remove:
population = self.animal_populations.pop(population_id)
species_name = population['species']
print(f"{self.animal_species[species_name]['name']} 种群已灭绝")
self.stats['animals_by_species'][species_name] = 0
except Exception as e:
print(f"✗ 动物种群更新失败: {e}")
def _update_animal_instances(self, dt: float):
"""更新动物实例"""
try:
# 更新动物实例状态
for instance_id, instance in self.animal_instances.items():
if not instance['alive']:
continue
# 更新饥饿度
instance['hunger'] = min(1.0, instance['hunger'] + 0.001 * dt / 3600)
# 更新能量
instance['energy'] = max(0.0, instance['energy'] - 0.0005 * dt / 3600)
# 如果饥饿度太高或能量太低,健康度下降
if instance['hunger'] > 0.8 or instance['energy'] < 0.2:
self.update_animal_health(instance_id, -0.0001 * dt / 3600)
except Exception as e:
print(f"✗ 动物实例更新失败: {e}")
def _update_animal_behaviors(self, dt: float):
"""更新动物行为"""
try:
# 在实际实现中,这里会更新动物的行为状态
# 如决定是否进食、移动、休息或交配
pass
except Exception as e:
print(f"✗ 动物行为更新失败: {e}")
def _calculate_environment_suitability(self, species_name: str) -> float:
"""
计算环境适宜性
Args:
species_name: 动物种类名称
Returns:
适宜性评分 (0.0-1.0)
"""
try:
species_info = self.animal_species[species_name]
# 基于植被密度的适宜性
vegetation_suitability = self.environment_factors['vegetation_density']
# 基于水可用性的适宜性
water_suitability = self.environment_factors['water_availability']
# 基于温度的适宜性
temperature = self.environment_factors['temperature']
if species_name in ['rabbit', 'deer']:
# 草食动物适宜温度范围
temp_suitability = max(0.0, 1.0 - abs(temperature - 20.0) / 20.0)
elif species_name in ['wolf', 'fox']:
# 肉食动物适宜温度范围
temp_suitability = max(0.0, 1.0 - abs(temperature - 15.0) / 25.0)
else:
temp_suitability = 1.0
# 综合评分
overall_suitability = (
vegetation_suitability * 0.4 +
water_suitability * 0.3 +
temp_suitability * 0.3
)
return max(0.0, min(1.0, overall_suitability))
except Exception as e:
print(f"✗ 环境适宜性计算失败: {e}")
return 0.5
def get_animal_species(self) -> List[str]:
"""
获取所有动物种类
Returns:
动物种类列表
"""
return list(self.animal_species.keys())
def get_animal_info(self, species_name: str) -> Optional[Dict[str, Any]]:
"""
获取动物种类信息
Args:
species_name: 动物种类名称
Returns:
动物信息字典或None
"""
return self.animal_species.get(species_name)
def create_animal_instance(self, species_name: str, position: tuple,
initial_age: float = 0.0, initial_health: float = 1.0) -> int:
"""
创建动物实例
Args:
species_name: 动物种类名称
position: 位置坐标 (x, y, z)
initial_age: 初始年龄
initial_health: 初始健康度 (0.0-1.0)
Returns:
动物实例ID
"""
try:
if species_name not in self.animal_species:
print(f"✗ 无效的动物种类: {species_name}")
return -1
instance_id = self.instance_counter
self.instance_counter += 1
# 获取动物种类信息
animal_info = self.animal_species[species_name]
# 创建实例数据
instance_data = {
'id': instance_id,
'species': species_name,
'position': position,
'age': initial_age,
'health': initial_health,
'alive': True,
'hunger': 0.0,
'energy': 1.0,
'state': 'resting', # 初始状态为休息
'destination': None, # 移动目标
'creation_time': time.time(),
'last_update': time.time()
}
# 存储实例
self.animal_instances[instance_id] = instance_data
# 添加到状态跟踪
self.animal_states['resting'].append(instance_id)
print(f"✓ 动物实例已创建: {animal_info['name']} (ID: {instance_id})")
return instance_id
except Exception as e:
print(f"✗ 动物实例创建失败: {e}")
import traceback
traceback.print_exc()
return -1
def remove_animal_instance(self, instance_id: int) -> bool:
"""
移除动物实例
Args:
instance_id: 动物实例ID
Returns:
是否移除成功
"""
try:
if instance_id not in self.animal_instances:
print(f"✗ 动物实例不存在: {instance_id}")
return False
# 从状态跟踪中移除
for state_list in self.animal_states.values():
if instance_id in state_list:
state_list.remove(instance_id)
# 移除实例
del self.animal_instances[instance_id]
print(f"✓ 动物实例已移除: ID {instance_id}")
return True
except Exception as e:
print(f"✗ 动物实例移除失败: {e}")
import traceback
traceback.print_exc()
return False
def get_animal_instance(self, instance_id: int) -> Optional[Dict[str, Any]]:
"""
获取动物实例信息
Args:
instance_id: 动物实例ID
Returns:
动物实例信息或None
"""
return self.animal_instances.get(instance_id)
def get_all_animal_instances(self) -> Dict[int, Dict[str, Any]]:
"""
获取所有动物实例
Returns:
所有动物实例字典
"""
return self.animal_instances.copy()
def update_environment_factors(self, factors: Dict[str, float]):
"""
更新环境因子
Args:
factors: 环境因子字典
"""
self.environment_factors.update(factors)
print(f"✓ 环境因子已更新: {factors}")
def get_environment_factors(self) -> Dict[str, float]:
"""
获取环境因子
Returns:
环境因子字典
"""
return self.environment_factors.copy()
def get_population_data(self) -> Dict[int, Dict[str, Any]]:
"""
获取种群数据
Returns:
种群数据字典
"""
return self.animal_populations.copy()
def set_behavior_config(self, config: Dict[str, float]):
"""
设置行为配置
Args:
config: 行为配置字典
"""
self.behavior_config.update(config)
print(f"✓ 行为配置已更新: {self.behavior_config}")
def get_behavior_config(self) -> Dict[str, float]:
"""
获取行为配置
Returns:
行为配置字典
"""
return self.behavior_config.copy()
def simulate_feeding(self, animal_species: str, food_type: str, amount: float) -> float:
"""
模拟进食过程
Args:
animal_species: 动物种类
food_type: 食物类型
amount: 食物量
Returns:
实际消耗的食物量
"""
try:
if animal_species not in self.animal_species:
return 0.0
# 获取进食效率
efficiency = self.behavior_config['feeding_efficiency']
actual_consumption = amount * efficiency
# 更新统计信息
self.stats['feedings'] += 1
print(f"{animal_species} 进食了 {actual_consumption:.2f} 单位的 {food_type}")
return actual_consumption
except Exception as e:
print(f"✗ 进食模拟失败: {e}")
return 0.0
def update_animal_health(self, instance_id: int, health_change: float):
"""
更新动物健康度
Args:
instance_id: 动物实例ID
health_change: 健康度变化值
"""
try:
if instance_id not in self.animal_instances:
return
instance = self.animal_instances[instance_id]
new_health = max(0.0, min(1.0, instance['health'] + health_change))
instance['health'] = new_health
# 如果健康度为0动物死亡
if new_health <= 0.0:
instance['alive'] = False
print(f"✓ 动物实例死亡: ID {instance_id}")
except Exception as e:
print(f"✗ 动物健康度更新失败: {e}")
def get_animal_states(self) -> Dict[str, List[int]]:
"""
获取动物状态分布
Returns:
动物状态字典
"""
# 返回状态副本,避免外部修改
return {state: ids.copy() for state, ids in self.animal_states.items()}
def update_animal_state(self, instance_id: int, new_state: str) -> bool:
"""
更新动物状态
Args:
instance_id: 动物实例ID
new_state: 新状态
Returns:
是否更新成功
"""
try:
if instance_id not in self.animal_instances:
print(f"✗ 动物实例不存在: {instance_id}")
return False
if new_state not in self.animal_states:
print(f"✗ 无效的动物状态: {new_state}")
return False
# 从旧状态列表中移除
for state_list in self.animal_states.values():
if instance_id in state_list:
state_list.remove(instance_id)
# 添加到新状态列表
self.animal_states[new_state].append(instance_id)
# 更新实例状态
self.animal_instances[instance_id]['state'] = new_state
# 更新移动统计
if new_state == 'moving':
self.stats['movements'] += 1
print(f"✓ 动物状态已更新: ID {instance_id} -> {new_state}")
return True
except Exception as e:
print(f"✗ 动物状态更新失败: {e}")
return False
def get_stats(self) -> Dict[str, Any]:
"""
获取统计信息
Returns:
统计信息字典
"""
return self.stats.copy()
def reset_stats(self):
"""重置统计信息"""
self.stats = {
'total_animals': 0,
'animals_by_species': {species: 0 for species in self.animal_species.keys()},
'births': 0,
'deaths': 0,
'feedings': 0,
'movements': 0
}
print("✓ 动物模拟器统计信息已重置")
def get_species_ecological_role(self, species_name: str) -> Dict[str, bool]:
"""
获取物种的生态角色
Args:
species_name: 物种名称
Returns:
生态角色字典
"""
try:
if species_name not in self.animal_species:
return {}
species_info = self.animal_species[species_name]
return {
'pollinator': species_info.get('pollinator', False),
'seed_disperser': species_info.get('seed_disperser', False),
'predator': species_info['diet'] == 'carnivore',
'herbivore': species_info['diet'] in ['herbivore', 'omnivore']
}
except Exception as e:
print(f"✗ 生态角色获取失败: {e}")
return {}