修改代码，添加一些功能：
   - 允许用户点击地图上的空白格子来手动添加植物或动物。
   - 允许用户点击动物查看其详细状态（如能量、年龄等）。
```python
import tkinter as tk
from tkinter import messagebox
import random
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


class Animal:
    def __init__(self, energy, x, y, age=0):
        self.energy = energy
        self.x = x
        self.y = y
        self.age = age  # 添加年龄属性

    def is_alive(self):
        return self.energy > 0

    def consume_energy(self, amount):
        self.energy -= amount

    def move(self, max_x, max_y):
        new_x = self.x + random.choice([-1, 1])
        new_y = self.y + random.choice([-1, 1])
        self.x = max(0, min(max_x - 1, new_x))
        self.y = max(0, min(max_y - 1, new_y))

    def act(self, targets, max_x, max_y):
        self.move(max_x, max_y)
        if self.energy >= self.breed_energy:
            choice = random.choice(["eat", "breed"])
        else:
            choice = "eat"
        if choice == "eat" and targets:
            self.eat(targets, max_x, max_y)
        elif choice == "breed":
            self.energy -= self.breed_energy
            return self.__class__(self.breed_energy, self.x, self.y)
        self.consume_energy(self.consume_rate)

    def eat(self, targets, max_x, max_y):
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
                nx, ny = (self.x + dx) % max_x, (self.y + dy) % max_y
                for target in targets:
                    if (nx, ny) == (target.x, target.y):
                        self.energy += self.eat_energy
                        targets.remove(target)
                        self.x, self.y = target.x, target.y
                        return


class Herbivore(Animal):
    breed_energy = 5
    eat_energy = 3
    consume_rate = 1


class Carnivore(Animal):
    breed_energy = 10
    eat_energy = 6
    consume_rate = 2


class Plant:
    def __init__(self, x, y):
        self.x = x
        self.y = y


def simulate_round(herbivores, carnivores, plants, max_x, max_y):
    for animal_list, act_target in [
        (herbivores, plants), (carnivores, herbivores)
    ]:
        for i in range(len(animal_list) - 1, -1, -1):
            baby = animal_list[i].act(act_target, max_x, max_y)
            if baby:
                animal_list.append(baby)
            if not animal_list[i].is_alive():
                del animal_list[i]


def ecosystem_simulation(rounds, num_plants, num_herbivores, num_carnivores, canvas, max_x, max_y, chart_frame, root):
    plants = [Plant(random.randint(0, max_x-1), random.randint(0, max_y-1)) for _ in range(num_plants)]
    herbivores = [Herbivore(5, random.randint(0, max_x-1), random.randint(0, max_y-1)) for _ in range(num_herbivores)]
    carnivores = [Carnivore(10, random.randint(0, max_x-1), random.randint(0, max_y-1)) for _ in range(num_carnivores)]

    herbivores_data = []
    carnivores_data = []
    rounds_data = []

    def simulate_and_update(round):
        if round >= rounds:
            messagebox.showinfo("Simulation", "Simulation ended.")
            return

        simulate_round(herbivores, carnivores, plants, max_x, max_y)
        draw_map(canvas, plants, herbivores, carnivores, max_x, max_y)

        plant_growth = random.randint(3, 5)
        for _ in range(plant_growth):
            plants.append(Plant(random.randint(0, max_x-1), random.randint(0, max_y-1)))

        herbivores_data.append(len(herbivores))
        carnivores_data.append(len(carnivores))
        rounds_data.append(round + 1)

        update_chart(chart_frame, rounds_data, herbivores_data, carnivores_data)

        if not herbivores and not carnivores:
            messagebox.showinfo("Simulation", "All animals died.")
            return

        root.after(250, lambda: simulate_and_update(round + 1))

    simulate_and_update(0)


def draw_map(canvas, plants, herbivores, carnivores, max_x, max_y):
    canvas.delete("plants")
    canvas.delete("herbivores")
    canvas.delete("carnivores")

    cell_size = 20
    for plant in plants:
        x1, y1 = plant.x * cell_size, plant.y * cell_size
        x2, y2 = x1 + cell_size, y1 + cell_size
        canvas.create_rectangle(x1, y1, x2, y2, fill="green", tags="plants")

    for herbivore in herbivores:
        x1, y1 = herbivore.x * cell_size, herbivore.y * cell_size
        x2, y2 = x1 + cell_size, y1 + cell_size
        canvas.create_oval(x1, y1, x2, y2, fill="blue", tags="herbivores")
        canvas.create_text(x1 + cell_size / 2, y1 + cell_size / 2, text=str(herbivore.energy), fill="white", tags="herbivores")

    for carnivore in carnivores:
        x1, y1 = carnivore.x * cell_size, carnivore.y * cell_size
        x2, y2 = x1 + cell_size, y1 + cell_size
        canvas.create_oval(x1, y1, x2, y2, fill="red", tags="carnivores")
        canvas.create_text(x1 + cell_size / 2, y1 + cell_size / 2, text=str(carnivore.energy), fill="white", tags="carnivores")

    canvas.update()


def update_chart(chart_frame, rounds, herbivores_data, carnivores_data):
    for widget in chart_frame.winfo_children():
        widget.destroy()

    fig, ax = plt.subplots()
    ax.plot(rounds, herbivores_data, label='Herbivores')
    ax.plot(rounds, carnivores_data, label='Carnivores')
    ax.set_xlabel('Round')
    ax.set_ylabel('Number of Animals')
    ax.legend()

    chart = FigureCanvasTkAgg(fig, master=chart_frame)
    chart.draw()
    chart.get_tk_widget().pack()


def start_simulation():
    num_plants = int(plants_entry.get())
    num_herbivores = int(herbivores_entry.get())
    num_carnivores = int(carnivores_entry.get())
    ecosystem_simulation(500, num_plants, num_herbivores, num_carnivores, canvas, 20, 20, chart_frame, root)


root = tk.Tk()
root.title("生态系统模拟")

tk.Label(root, text="初始植物数量（基准值：40）：").grid(row=0, column=0)
plants_entry = tk.Entry(root)
plants_entry.grid(row=0, column=1)

tk.Label(root, text="初始食草动物数量（基准值：12）：").grid(row=1, column=0)
herbivores_entry = tk.Entry(root)
herbivores_entry.grid(row=1, column=1)

tk.Label(root, text="初始食肉动物数量（基准值：7）：").grid(row=2, column=0)
carnivores_entry = tk.Entry(root)
carnivores_entry.grid(row=2, column=1)

start_button = tk.Button(root, text="开始模拟", command=start_simulation)
start_button.grid(row=3, column=0, columnspan=2)

canvas = tk.Canvas(root, width=400, height=400, bg="white")
canvas.grid(row=4, column=0, columnspan=2)

chart_frame = tk.Frame(root)
chart_frame.grid(row=0, column=2, rowspan=5)

root.mainloop()
```