Adam Bandel


Predator-Prey Neural Net Simulation

May 2025
Type: game
Code: 8k lines
Files: 112
Active: May 2025 — May 2025
Stack:
PythonPyGameModernGLNumPyPyOpenGL
Tags:
aisimulationgame-dev

Overview

A real-time evolutionary ecosystem simulation where neural network-powered creatures compete for survival. Prey seek food and flee predators, predators hunt to survive, and both species evolve through genetic inheritance and mutation. The simulation features procedurally generated terrain, dynamic weather systems, day/night cycles, and hardware-accelerated rendering.

The project explores emergent behavior through simple rules: creatures with better-suited genes and neural networks survive longer and reproduce more, leading to population dynamics and evolutionary pressures that mirror real ecological systems.

Screenshots

Simulation Overview

Creature Interactions

Day/Night Cycle

Problem

Traditional artificial life simulations often rely on hand-coded behavior rules that produce predictable outcomes. I wanted to explore whether meaningful survival strategies could emerge from neural networks that evolve through natural selection rather than explicit training, and whether complex population dynamics could arise from simple genetic rules.

Approach

The simulation combines evolutionary algorithms with neural networks to create an ecosystem where behavior evolves organically.

Stack

Challenges

Outcomes

The simulation successfully demonstrates emergent evolutionary behavior. Prey populations develop faster movement genes when predator pressure is high. Predators evolve improved perception when prey become harder to catch. The neural networks, despite their simplicity (4-5 inputs, 5 outputs), learn effective survival strategies through evolution alone.

Key technical achievements:

Implementation Notes

Neural Network Evolution

Each creature’s brain is a simple feed-forward network where weights are encoded in its genome:

# Prey brain inputs: [hunger, fear, light_level, food_distance]
# Outputs: [food_weight, flee_weight, mate_weight, wall_weight, wander_weight]

class FeedForwardNet:
    def forward(self, inputs: list[float]) -> list[float]:
        x = inputs
        for i, (weights, bias) in enumerate(self.layers):
            x = [max(0, sum(w * xi for w, xi in zip(row, x)) + b)
                 for row, b in zip(weights, bias)]  # ReLU activation
        return x

Offspring inherit averaged parent weights with 10% mutation rate, allowing beneficial behavioral adaptations to spread through the population.

Spatial Indexing Strategy

The simulation uses a hybrid approach based on entity density:

class UniformGrid(SpatialIndex):
    def query_circle(self, cx, cy, radius):
        # O(1) cell lookup + O(k) entity checks where k << n
        min_cell_x = int((cx - radius) / self.cell_size)
        max_cell_x = int((cx + radius) / self.cell_size)
        # ... check only cells that intersect the query circle

Environmental Systems

Weather uses a Markov chain model where state transitions affect plant growth:

State Sunny Rain Drought Cold Snap
Sunny 0.7 0.2 0.05 0.05
Rain 0.3 0.5 0.1 0.1
Drought 0.4 0.1 0.4 0.1
Cold Snap 0.3 0.2 0.1 0.4

Rain increases plant spawn rates by 1.5x, creating seasonal abundance that drives population cycles.

View on GitHub →


Related Posts

No posts yet.