I changed it quite a bit, and improve some code here and there. could you optimize it and have it visualized? also improve it as well by adding some needed features.
```
import random
import math
import time
from dataclasses import dataclass
from typing import List, Optional
from enum import Enum, auto

# Constants
@dataclass(frozen=True)
class WorldConfig:
    SIZE: int = 100
    MAX_HEALTH: int = 100
    MAX_HUNGER: int = 100
    MAX_THIRST: int = 100
    FOOD_ENERGY: int = 50
    WATER_ENERGY: int = 50
    REPRODUCTION_AGE: int = 10
    MOVE_ENERGY_COST: float = 1.0
    INTERACTION_DISTANCE: int = 2
    INITIAL_POPULATION: int = 5
    MAX_SIMULATION_TIME: int = 200
    SPAWN_RATE: float = 0.3
    MUTATION_RANGE: float = 5.0
    
class ResourceType(Enum):
    FOOD = auto()
    WATER = auto()

@dataclass
class Position:
    x: float
    y: float
    
    def distance_to(self, other: 'Position') -> float:
        return math.hypot(self.x - other.x, self.y - other.y)
    
    def move_towards(self, target: 'Position', speed: float) -> None:
        dx = target.x - self.x
        dy = target.y - self.y
        distance = math.hypot(dx, dy)
        if distance == 0:
            return
        
        self.x += (dx / distance) * speed
        self.y += (dy / distance) * speed
        self._clamp_position()
    
    def move_random(self, speed: float) -> None:
        angle = random.uniform(0, 2 * math.pi)
        self.x += math.cos(angle) * speed
        self.y += math.sin(angle) * speed
        self._clamp_position()
    
    def _clamp_position(self) -> None:
        self.x = max(0, min(self.x, WorldConfig.SIZE))
        self.y = max(0, min(self.y, WorldConfig.SIZE))

class Resource:
    def __init__(self, resource_type: ResourceType):
        self.position = Position(
            random.uniform(0, WorldConfig.SIZE),
            random.uniform(0, WorldConfig.SIZE)
        )
        self.resource_type = resource_type
        self.consumed = False

class Organism:
    def __init__(
        self,
        position: Optional[Position] = None,
        generation: int = 1,
        parent_smartness: float = 50.0
    ):
        self.position = position or Position(
            random.uniform(0, WorldConfig.SIZE),
            random.uniform(0, WorldConfig.SIZE)
        )
        self.health = WorldConfig.MAX_HEALTH
        self.hunger = random.uniform(20, 40)
        self.thirst = random.uniform(20, 40)
        self.age = 0
        self.generation = generation
        self.alive = True
        self.smartness = max(0, min(100, parent_smartness + random.uniform(
            -WorldConfig.MUTATION_RANGE,
            WorldConfig.MUTATION_RANGE
        )))
        
    @property
    def movement_speed(self) -> float:
        return self.smartness * 0.1
    
    def needs_food(self) -> bool:
        return self.hunger > 50
    
    def needs_water(self) -> bool:
        return self.thirst > 50
    
    def can_reproduce(self) -> bool:
        return (
            self.age >= WorldConfig.REPRODUCTION_AGE
            and self.health > 70
        )
    
    def consume_resource(self, resource: Resource) -> None:
        if resource.resource_type == ResourceType.FOOD:
            self.hunger = max(0, self.hunger - WorldConfig.FOOD_ENERGY)
        else:
            self.thirst = max(0, self.thirst - WorldConfig.WATER_ENERGY)
        resource.consumed = True
    
    def update(self) -> None:
        if not self.alive:
            return
            
        self.hunger += 5
        self.thirst += 5
        self.age += 1
        
        # Health management
        if self.hunger >= WorldConfig.MAX_HUNGER or self.thirst >= WorldConfig.MAX_THIRST:
            self.health -= 10
        else:
            self.health = min(WorldConfig.MAX_HEALTH, self.health + 2)
        
        # Check for death conditions
        if self.health <= 0 or self.age > 100:
            self.alive = False
    
    def reproduce(self) -> 'Organism':
        self.health -= 20  # Reproduction cost
        return Organism(
            position=Position(self.position.x, self.position.y),
            generation=self.generation + 1,
            parent_smartness=self.smartness
        )

class Environment:
    def __init__(self):
        self.organisms: List[Organism] = [
            Organism() for _ in range(WorldConfig.INITIAL_POPULATION)
        ]
        self.resources: List[Resource] = []
        self.time = 0
        self.statistics = SimulationStatistics()
    
    def spawn_resources(self) -> None:
        if random.random() < WorldConfig.SPAWN_RATE:
            self.resources.append(Resource(ResourceType.FOOD))
        if random.random() < WorldConfig.SPAWN_RATE:
            self.resources.append(Resource(ResourceType.WATER))
    
    def find_nearest_resource(
        self,
        position: Position,
        resource_type: ResourceType
    ) -> Optional[Resource]:
        available_resources = [
            r for r in self.resources
            if r.resource_type == resource_type and not r.consumed
        ]
        
        if not available_resources:
            return None
            
        return min(
            available_resources,
            key=lambda r: position.distance_to(r.position)
        )
    
    def update(self) -> None:
        self.time += 1
        self.spawn_resources()
        
        new_organisms = []
        stats = SimulationStatistics()
        
        for organism in self.organisms:
            if not organism.alive:
                continue
                
            organism.update()
            if organism.alive:
                stats.update_from_organism(organism)
                
                # Handle reproduction
                if organism.can_reproduce():
                    new_organisms.append(organism.reproduce())
                
                # Handle movement and resource consumption
                self._handle_organism_behavior(organism)
        
        # Update simulation state
        self.resources = [r for r in self.resources if not r.consumed]
        self.organisms = [o for o in self.organisms if o.alive] + new_organisms
        
        # Update and display statistics
        stats.display(self.time, len(self.organisms))
        self.statistics = stats
    
    def _handle_organism_behavior(self, organism: Organism) -> None:
        if organism.needs_food():
            nearest_food = self.find_nearest_resource(
                organism.position,
                ResourceType.FOOD
            )
            self._handle_resource_interaction(organism, nearest_food)
        elif organism.needs_water():
            nearest_water = self.find_nearest_resource(
                organism.position,
                ResourceType.WATER
            )
            self._handle_resource_interaction(organism, nearest_water)
        else:
            organism.position.move_random(organism.movement_speed)
            organism.health -= WorldConfig.MOVE_ENERGY_COST
    
    def _handle_resource_interaction(
        self,
        organism: Organism,
        resource: Optional[Resource]
    ) -> None:
        if not resource:
            organism.position.move_random(organism.movement_speed)
            organism.health -= WorldConfig.MOVE_ENERGY_COST
            return
            
        distance = organism.position.distance_to(resource.position)
        
        if distance <= WorldConfig.INTERACTION_DISTANCE:
            organism.consume_resource(resource)
        else:
            organism.position.move_towards(
                resource.position,
                organism.movement_speed
            )
            organism.health -= WorldConfig.MOVE_ENERGY_COST

class SimulationStatistics:
    def __init__(self):
        self.total_hunger = 0
        self.total_thirst = 0
        self.total_smartness = 0
        self.total_organisms = 0
    
    def update_from_organism(self, organism: Organism) -> None:
        self.total_hunger += organism.hunger
        self.total_thirst += organism.thirst
        self.total_smartness += organism.smartness
        self.total_organisms += 1
    
    def display(self, time: int, population: int) -> None:
        if self.total_organisms == 0:
            print("All organisms have died.")
            return
            
        print(f"\nTime: {time}")
        print(f"Population: {population}")
        print(f"Average Hunger: {self.total_hunger / self.total_organisms:.2f}")
        print(f"Average Thirst: {self.total_thirst / self.total_organisms:.2f}")
        print(f"Average Smartness: {self.total_smartness / self.total_organisms:.2f}")
        print("-" * 50)

def simulate():
    env = Environment()
    try:
        while (
            env.organisms
            and env.time <= WorldConfig.MAX_SIMULATION_TIME
        ):
            env.update()
            time.sleep(0.5)
    except KeyboardInterrupt:
        print("\nSimulation interrupted by user.")
    finally:
        print(f"\nSimulation ended at time {env.time}")
        print(f"Final population: {len(env.organisms)}")

if __name__ == "__main__":
    simulate()
```