aW1wb3J0IG51bXB5IGFzIG5wCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKZnJvbSBtYXRwbG90bGliLmNvbG9ycyBpbXBvcnQgTGluZWFyU2VnbWVudGVkQ29sb3JtYXAKCiMg6Ieq5a6a5LmJ6aKc6Imy5pig5bCECmdlb19jbWFwID0gTGluZWFyU2VnbWVudGVkQ29sb3JtYXAuZnJvbV9saXN0KCdnZW8nLCBbJyMwMDQ0MDAnLCcjMjI4ODIyJywnIzg4NzcyMicsJyM3NzQ0MTEnXSkKY2l0eV9jbWFwID0gTGluZWFyU2VnbWVudGVkQ29sb3JtYXAuZnJvbV9saXN0KCdjaXR5JywgWycjMDAwMDAwJywnIzY2NjY2NicsJyNhYWFhYWEnXSkKZmlyZV9jbWFwID0gTGluZWFyU2VnbWVudGVkQ29sb3JtYXAuZnJvbV9saXN0KCdmaXJlJywgWycjMzMwMDAwJywnI2ZmMzMwMCcsJyNmZmZmMDAnXSkKCmNsYXNzIFBsYW5ldDoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBzaXplPTEwMDApOgogICAgICAgIHNlbGYuc2l6ZSA9IHNpemUKICAgICAgICBzZWxmLmdlbmVyYXRlX3RlcnJhaW4oKQogICAgICAgIHNlbGYuZ2VuZXJhdGVfaHlkcm9sb2d5KCkKICAgICAgICBzZWxmLmdlbmVyYXRlX2NpdGllcygpCiAgICAgICAgc2VsZi5nZW5lcmF0ZV9iaW9tZXMoKQogICAgICAgIAogICAgZGVmIGdlbmVyYXRlX3RlcnJhaW4oc2VsZik6CiAgICAgICAgJnF1b3Q7JnF1b3Q7JnF1b3Q75L2/55SoUGVybGlu5Zmq5aOw55Sf5oiQ5Zyw5b2iJnF1b3Q7JnF1b3Q7JnF1b3Q7CiAgICAgICAgeCA9IG5wLmxpbnNwYWNlKDAsIDEwLCBzZWxmLnNpemUpCiAgICAgICAgeSA9IG5wLmxpbnNwYWNlKDAsIDEwLCBzZWxmLnNpemUpCiAgICAgICAgc2VsZi50ZXJyYWluID0gbnAucmFuZG9tLnJhbmQoc2VsZi5zaXplLCBzZWxmLnNpemUpCiAgICAgICAgCiAgICBkZWYgZ2VuZXJhdGVfaHlkcm9sb2d5KHNlbGYpOgogICAgICAgICZxdW90OyZxdW90OyZxdW90O+eUn+aIkOawtOWfn+WIhuW4gyZxdW90OyZxdW90OyZxdW90OwogICAgICAgIHNlbGYud2F0ZXIgPSBucC56ZXJvcygoc2VsZi5zaXplLCBzZWxmLnNpemUpKQogICAgICAgICMg5re75Yqg6ZqP5py65rC05Z+f5ZKM5rKz5rWBCiAgICAgICAgc2VsZi53YXRlciArPSBucC5yYW5kb20ucmFuZCgqc2VsZi53YXRlci5zaGFwZSkqMC4zCiAgICAgICAgc2VsZi53YXRlciA9IG5wLmNsaXAoc2VsZi53YXRlciwgMCwgMSkKICAgICAgICAKICAgIGRlZiBnZW5lcmF0ZV9jaXRpZXMoc2VsZik6CiAgICAgICAgJnF1b3Q7JnF1b3Q7JnF1b3Q755Sf5oiQ5Z+O5biC5YiG5biD77yI566A5YyW5qih5Z6L77yJJnF1b3Q7JnF1b3Q7JnF1b3Q7CiAgICAgICAgc2VsZi5jaXRpZXMgPSBucC56ZXJvcygoc2VsZi5zaXplLCBzZWxmLnNpemUpKQogICAgICAgICMg5Zyo5bmz5Z2m5Yy65Z+f55Sf5oiQ5Z+O5biCCiAgICAgICAgZmxhdF9hcmVhcyA9IChzZWxmLnRlcnJhaW4gJmd0OyAwLjQpICZhbXA7IChzZWxmLnRlcnJhaW4gJmx0OyAwLjYpCiAgICAgICAgc2VsZi5jaXRpZXNbZmxhdF9hcmVhc10gPSBucC5yYW5kb20ucmFuZChucC5zdW0oZmxhdF9hcmVhcykpKjAuOAogICAgICAgIAogICAgZGVmIGdlbmVyYXRlX2Jpb21lcyhzZWxmKToKICAgICAgICAmcXVvdDsmcXVvdDsmcXVvdDvnlJ/miJDnlJ/niannvqTokL3liIbluIMmcXVvdDsmcXVvdDsmcXVvdDsKICAgICAgICBzZWxmLmJpb21lcyA9IG5wLnplcm9zKChzZWxmLnNpemUsIHNlbGYuc2l6ZSkpCiAgICAgICAgIyDln7rkuo7msLTlkozlnLDlvaLnlJ/miJDnlJ/niakKICAgICAgICBzZWxmLmJpb21lcyA9IG5wLmNsaXAoKDEtc2VsZi53YXRlcikqc2VsZi50ZXJyYWluLCAwLCAxKQogICAgICAgIAogICAgZGVmIGFwcGx5X2ltcGFjdChzZWxmLCBpbXBhY3RfcG9zLCBlbmVyZ3kpOgogICAgICAgICZxdW90OyZxdW90OyZxdW90O+W6lOeUqOeisOaSnuW9seWTjSZxdW90OyZxdW90OyZxdW90OwogICAgICAgICMg5Yib5bu65Yay5Ye75rOi5o6p5qihCiAgICAgICAgeCwgeSA9IG5wLm9ncmlkWzpzZWxmLnNpemUsIDpzZWxmLnNpemVdCiAgICAgICAgZGlzdCA9IG5wLnNxcnQoKHgtaW1wYWN0X3Bvc1swXSkqKjIgKyAoeS1pbXBhY3RfcG9zWzFdKSoqMikKICAgICAgICAKICAgICAgICAjIOWcsOW9ouaUueWPmO+8iOW8ueWdkeW9ouaIkO+8iQogICAgICAgIHNlbGYudGVycmFpbiAtPSBucC5leHAoLWRpc3QvKGVuZXJneSowLjEpKSAqIDAuNQogICAgICAgIHNlbGYudGVycmFpbiA9IG5wLmNsaXAoc2VsZi50ZXJyYWluLCAwLCAxKQogICAgICAgIAogICAgICAgICMg5rC05Z+f6JK45Y+RCiAgICAgICAgc2VsZi53YXRlciA9IG5wLndoZXJlKGRpc3QgJmx0OyBlbmVyZ3kqMC4yLCAwLCBzZWxmLndhdGVyKQogICAgICAgIAogICAgICAgICMg5Z+O5biC56C05Z2PCiAgICAgICAgY2l0eV9kYW1hZ2UgPSBucC5leHAoLWRpc3QvKGVuZXJneSowLjA1KSkKICAgICAgICBzZWxmLmNpdGllcyA9IG5wLmNsaXAoc2VsZi5jaXRpZXMgLSBjaXR5X2RhbWFnZSoyLCAwLCAxKQogICAgICAgIAogICAgICAgICMg5byV5Y+R5bGx54GrCiAgICAgICAgc2VsZi5maXJlID0gbnAuZXhwKC1kaXN0LyhlbmVyZ3kqMC4xNSkpICogKDEgLSBzZWxmLndhdGVyKQogICAgICAgIAogICAgICAgICMg55Sf54mp54Gt57udCiAgICAgICAgc2VsZi5iaW9tZXMgPSBucC53aGVyZShkaXN0ICZsdDsgZW5lcmd5KjAuMywgMCwgc2VsZi5iaW9tZXMpCgpjbGFzcyBDb2xsaXNpb25TaW11bGF0b3I6CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgc2VsZi5lYXJ0aCA9IFBsYW5ldCgpCiAgICAgICAgc2VsZi5pbXBhY3RfZW5lcmd5ID0gMAogICAgICAgIHNlbGYuaW1wYWN0X3Bvc2l0aW9uID0gKDUwMCwgNTAwKQogICAgICAgIAogICAgZGVmIHNpbXVsYXRlX2ltcGFjdChzZWxmLCBlbmVyZ3k9MTAwKToKICAgICAgICAmcXVvdDsmcXVvdDsmcXVvdDvmiafooYznorDmkp7mqKHmi58mcXVvdDsmcXVvdDsmcXVvdDsKICAgICAgICBzZWxmLmltcGFjdF9lbmVyZ3kgPSBlbmVyZ3kKICAgICAgICBzZWxmLmVhcnRoLmFwcGx5X2ltcGFjdChzZWxmLmltcGFjdF9wb3NpdGlvbiwgZW5lcmd5KQogICAgICAgIAogICAgZGVmIHZpc3VhbGl6ZShzZWxmKToKICAgICAgICAmcXVvdDsmcXVvdDsmcXVvdDvliJvlu7rlj6/op4bljJbop4blm74mcXVvdDsmcXVvdDsmcXVvdDsKICAgICAgICBmaWcsIGF4cyA9IHBsdC5zdWJwbG90cygyLCAyLCBmaWdzaXplPSgyMCwgMjApKQogICAgICAgIAogICAgICAgICMg5Zyw5b2i5Zu+CiAgICAgICAgYXhzWzAsMF0uaW1zaG93KHNlbGYuZWFydGgudGVycmFpbiwgY21hcD1nZW9fY21hcCkKICAgICAgICBheHNbMCwwXS5zZXRfdGl0bGUoJ+WcsOi0qOe7k+aehCcpCiAgICAgICAgCiAgICAgICAgIyDmsLTmlofkuI7ln47luIIKICAgICAgICB3YXRlcl9tYXNrID0gbnAubWEubWFza2VkX3doZXJlKHNlbGYuZWFydGgud2F0ZXIgJmx0OyAwLjMsIHNlbGYuZWFydGgud2F0ZXIpCiAgICAgICAgYXhzWzAsMV0uaW1zaG93KHdhdGVyX21hc2ssIGNtYXA9J0JsdWVzJywgYWxwaGE9MC41KQogICAgICAgIGF4c1swLDFdLmltc2hvdyhzZWxmLmVhcnRoLmNpdGllcywgY21hcD1jaXR5X2NtYXAsIGFscGhhPTAuNykKICAgICAgICBheHNbMCwxXS5zZXRfdGl0bGUoJ+awtOWfn+S4juWfjuW4gicpCiAgICAgICAgCiAgICAgICAgIyDnlJ/mgIHkuI7lsbHngasKICAgICAgICBheHNbMSwwXS5pbXNob3coc2VsZi5lYXJ0aC5iaW9tZXMsIGNtYXA9J0dyZWVucycsIGFscGhhPTAuNykKICAgICAgICBmaXJlX21hc2sgPSBucC5tYS5tYXNrZWRfd2hlcmUoc2VsZi5lYXJ0aC5maXJlICZsdDsgMC4xLCBzZWxmLmVhcnRoLmZpcmUpCiAgICAgICAgYXhzWzEsMF0uaW1zaG93KGZpcmVfbWFzaywgY21hcD1maXJlX2NtYXAsIGFscGhhPTAuNikKICAgICAgICBheHNbMSwwXS5zZXRfdGl0bGUoJ+eUn+eJqee+pOiQveS4juWxseeBqycpCiAgICAgICAgCiAgICAgICAgIyDnu7zlkIjlvbHlk40KICAgICAgICBpbXBhY3RfYXJlYSA9IG5wLmV4cCgtbnAuc3F1YXJlKG5wLmxpbnNwYWNlKC0xLDEsMTAwMCkpKSpzZWxmLmltcGFjdF9lbmVyZ3kKICAgICAgICBheHNbMSwxXS5pbXNob3coc2VsZi5lYXJ0aC50ZXJyYWluLCBjbWFwPWdlb19jbWFwKQogICAgICAgIGF4c1sxLDFdLmltc2hvdyhpbXBhY3RfYXJlYSwgY21hcD0nUmVkcycsIGFscGhhPTAuNCwKICAgICAgICAgICAgICAgICAgICAgIGV4dGVudD0oc2VsZi5pbXBhY3RfcG9zaXRpb25bMV0tNTAwLCBzZWxmLmltcGFjdF9wb3NpdGlvblsxXSs1MDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuaW1wYWN0X3Bvc2l0aW9uWzBdKzUwMCwgc2VsZi5pbXBhY3RfcG9zaXRpb25bMF0tNTAwKSkKICAgICAgICBheHNbMSwxXS5zZXRfdGl0bGUoJ+e7vOWQiOeisOaSnuW9seWTjeWMuicpCiAgICAgICAgCiAgICAgICAgcGx0LnNob3coKQoKIyDov5DooYzmqKHmi58Kc2ltID0gQ29sbGlzaW9uU2ltdWxhdG9yKCkKc2ltLnNpbXVsYXRlX2ltcGFjdChlbmVyZ3k9MjAwKQpzaW0udmlzdWFsaXplKCk=
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# 自定义颜色映射
geo_cmap = LinearSegmentedColormap.from_list('geo', ['#004400','#228822','#887722','#774411'])
city_cmap = LinearSegmentedColormap.from_list('city', ['#000000','#666666','#aaaaaa'])
fire_cmap = LinearSegmentedColormap.from_list('fire', ['#330000','#ff3300','#ffff00'])
class Planet:
def __init__(self, size=1000):
self.size = size
self.generate_terrain()
self.generate_hydrology()
self.generate_cities()
self.generate_biomes()
def generate_terrain(self):
"""使用Perlin噪声生成地形"""
x = np.linspace(0, 10, self.size)
y = np.linspace(0, 10, self.size)
self.terrain = np.random.rand(self.size, self.size)
def generate_hydrology(self):
"""生成水域分布"""
self.water = np.zeros((self.size, self.size))
# 添加随机水域和河流
self.water += np.random.rand(*self.water.shape)*0.3
self.water = np.clip(self.water, 0, 1)
def generate_cities(self):
"""生成城市分布(简化模型)"""
self.cities = np.zeros((self.size, self.size))
# 在平坦区域生成城市
flat_areas = (self.terrain > 0.4) & (self.terrain < 0.6)
self.cities[flat_areas] = np.random.rand(np.sum(flat_areas))*0.8
def generate_biomes(self):
"""生成生物群落分布"""
self.biomes = np.zeros((self.size, self.size))
# 基于水和地形生成生物
self.biomes = np.clip((1-self.water)*self.terrain, 0, 1)
def apply_impact(self, impact_pos, energy):
"""应用碰撞影响"""
# 创建冲击波掩模
x, y = np.ogrid[:self.size, :self.size]
dist = np.sqrt((x-impact_pos[0])**2 + (y-impact_pos[1])**2)
# 地形改变(弹坑形成)
self.terrain -= np.exp(-dist/(energy*0.1)) * 0.5
self.terrain = np.clip(self.terrain, 0, 1)
# 水域蒸发
self.water = np.where(dist < energy*0.2, 0, self.water)
# 城市破坏
city_damage = np.exp(-dist/(energy*0.05))
self.cities = np.clip(self.cities - city_damage*2, 0, 1)
# 引发山火
self.fire = np.exp(-dist/(energy*0.15)) * (1 - self.water)
# 生物灭绝
self.biomes = np.where(dist < energy*0.3, 0, self.biomes)
class CollisionSimulator:
def __init__(self):
self.earth = Planet()
self.impact_energy = 0
self.impact_position = (500, 500)
def simulate_impact(self, energy=100):
"""执行碰撞模拟"""
self.impact_energy = energy
self.earth.apply_impact(self.impact_position, energy)
def visualize(self):
"""创建可视化视图"""
fig, axs = plt.subplots(2, 2, figsize=(20, 20))
# 地形图
axs[0,0].imshow(self.earth.terrain, cmap=geo_cmap)
axs[0,0].set_title('地质结构')
# 水文与城市
water_mask = np.ma.masked_where(self.earth.water < 0.3, self.earth.water)
axs[0,1].imshow(water_mask, cmap='Blues', alpha=0.5)
axs[0,1].imshow(self.earth.cities, cmap=city_cmap, alpha=0.7)
axs[0,1].set_title('水域与城市')
# 生态与山火
axs[1,0].imshow(self.earth.biomes, cmap='Greens', alpha=0.7)
fire_mask = np.ma.masked_where(self.earth.fire < 0.1, self.earth.fire)
axs[1,0].imshow(fire_mask, cmap=fire_cmap, alpha=0.6)
axs[1,0].set_title('生物群落与山火')
# 综合影响
impact_area = np.exp(-np.square(np.linspace(-1,1,1000)))*self.impact_energy
axs[1,1].imshow(self.earth.terrain, cmap=geo_cmap)
axs[1,1].imshow(impact_area, cmap='Reds', alpha=0.4,
extent=(self.impact_position[1]-500, self.impact_position[1]+500,
self.impact_position[0]+500, self.impact_position[0]-500))
axs[1,1].set_title('综合碰撞影响区')
plt.show()
# 运行模拟
sim = CollisionSimulator()
sim.simulate_impact(energy=200)
sim.visualize()